常用指令
从github中同步代码到本地,以github分支为master
为例
1 | git pull origin master |
从本地同步代码到github,以同步所有代码,github分支为master
为例:
1 | git add . |
查看当前所有远程分支
1 | git branch -a |
查看当前所有本地分支
1 | git branch |
新建分支
1 | git branch +名字 |
切换分支
1 | git checkout +名字 |
删除远程分支,以远程服务为origin,删除test分支为例
1 | git push origin --delete test |
显示某个commit的内容
1 | git show commit_id |
git所有分支
1 | git pull --all origin一次同步所有分支 |
冲突解决
下拉时冲突
git pull
遇到错误:error: Your local changes to the following files would be overwritten by merge:
方法1:如果你想保留刚才本地修改的代码,并把git服务器上的代码pull到本地(本地刚才修改的代码将会被暂时封存起来)
1 | git stash |
方法2:如果你想完全地覆盖本地的代码,只保留服务器端代码,则直接回退到上一个版本,再进行pull:
1 | git reset --hard |
上传时冲突
git push
的时候报错hint: Updates were rejected because the tip of your current branch is behind
。
解决方法:本地分支强行覆盖远程分支,以github分支为master
为例
1 | git push -u origin master -f |
建立与远程仓库的连接
分为两种情况,若是自己的代码,需要手动在github上建立仓库;若是别人的代码,需要首先将别人的代码fork过来。
这里以fork的few-shot-gnn
仓库为例,在本地仓库敲下面指令与远程仓库建立连接。
1 | git remote add origin git@github.com:zdaiot/few-shot-gnn |
如果报错,提示说fatal: remote origin already exists.
,这是因为你本地仓库直接git clone
别人仓库的代码,而不是你仓库的代码。解决方法为:
1 | git remote rm origin |
然后再建立连接。
重建与远程仓库的连接
若是直接git clone别人的代码,但是不想fork,想直接上传,则首先git clone下来别人的代码。
然后
1 | git remote rm origin |
打开自己的github,新建一个仓库,例如名称为few-shot-gnn
,建立与远程仓库的连接
1 | git remote add origin git@github.com:zdaiot/few-shot-gnn |
此时,若是直接git push
,提示说fatal: The current branch master has no upstream branch.
则执行
1 | git push -u origin --all |
这时,通常github上只会有一个分支,要是想推送所有分支的话。例如还有一个分支adaboost
需要执行
1 | git checkout adaboost |
使用git remote -v
可以看到当前远程分支还是指向的之前的链接。所以需要
1 | git remote rm origin |
.gitignore规则无效
据我所知导致.gitignore里的忽略规则失效只有两种情况,当然我对Git的使用和理解比较浅薄,也只能想到这两个方面:一种是忽略规则的语法错误,这种情形好处理,只要修正错误的语法就可以了。PS:本文不对语法错误的问题详细说明,毕竟每个人情况不同。排查语法问题这事我也不知道怎么举例,总之只要符合官方规范的就可以了,需要注意的好像也就一个路径问题吧?!
另一种则是本文要重点说明的情况:项目中的文件或目录已经被纳入到Git的版本管理里面/跟踪文件清单,此时你再往.gitignore里添加此文件/目录的忽略规则就会发现毫无作用,因为已经被Git跟踪(track)的文件/目录无法被.gitignore忽略掉!。
这里再对上面一段所说的进行详细说明,所谓“已经被纳入到Git的版本管理里面/跟踪文件清单”,大体上指的是下面的三种情况:
- 已使用add命令开始跟踪项目文件或者将修改的文件放入暂存区/索引
- 已使用commit命令提交更新到本地仓库
- 已使用push命令将项目文件推送到了Git远程仓库了(例如GitHub)
上述的三种操作只要进行了其中一项,再添加对应文件的忽略规则都是不生效的!PS:这三个命令在GUI客户端上一般都可以找到对应的按钮和操作。
未进行提交操作的处理方式
如果此时还未进行提交操作,赶紧使用如下命令可及时挽救:git rm --cached <file>
,其中<file>
表示要从暂存区移除出去的文件名或者目录路径,注意可以使用通配符。不过Git有自己的通配符规则,所以要注意下差异,例如官方文档有提到在*
号前面是需要加反斜杠\
的(我有测试过不加也没事但是最好按照规范来),结合上面的案例,因为我们要移除bin文件夹下的所有文件,所以完整的Git命令为(注意路径一定要正确):
1 | git rm --cached WebApplication1/WebApplication1/bin/\* |
这里要留意忽略规则的添加时机,在命令执行后会有不同的影响,假设忽略规则是在git rm --cached <file>
命令执行前就设置了,那么当命令执行完成后马上就可以看到效果,bin文件夹及里面的所有文件会被Git直接忽略。如果在命令执行后还没有添加忽略规则,你会发现bin文件夹下的文件变成未被跟踪的状态,也就是最初的状态,此时你再添加忽略规则这些文件就会被忽略了。
文件已经进行提交操作的处理方式
如果bin文件夹已经被Git跟踪并提交到了本地版本库甚至远程版本库(例如GitHub),解决方法和上一小节中的方法是一样的,依然是使用git rm --cached <file>
这个命令。PS:在执行此命令前Git最好能保持干净的状态,也就是”nothing to commit, working tree clean”。
注意!!!在命令执行后受影响的文件都会变成未跟踪状态,此时一定要马上使用git commit -m ‘备注信息’命令提交这部分修改,如果还未设置.gitignore文件则可以设置后一并提交此次更新到本地仓库。这里千万不要使用任何GUI客户端去操作!因为不同GUI客户端可能有不一样的执行结果(例如可能会将文件重新纳入跟踪,等于刚刚的操作白费了)。
远程仓库强制覆盖本地仓库
执行下面语句:
1 | git fetch --all && git reset --hard origin/master && git pull |
git 舍弃某个文件的更改
当我们使用git reset --hard
指令时会舍弃所有的文件更改,但是有的时候我们只想舍弃某一个文件的更改,以record.xlsx
文件为例,应该使用如下方式:
1 | # 查看文件的修改记录 |
git file is being edited by
当遇到这个问题的时候。通常显示的是一个nano编辑器。首先会问你是否选项,这个时候输入y
即可。然后会显示一般情况下的nano编辑器样子,按ctrl+o
,保持当前修改。然后会让你输入文件名,随便输入即可,然后回车,输入y
,最后按下ctrl+x
退出,git就会正常工作。
重写某个repo的Git历史
经常碰见一种情况是,提交到github的时候,没有使用的邮箱不对,导致在Github没有记录你的Contributions,解决方法是使用脚本来改变某个repo的Git历史。
在执行这段脚本前,你需要准备的信息:
Mac、Linux下打开Terminal,Windows下打开命令提示符(command prompt)
给你的repo创建一个全新的clone
1
2git clone --bare https://github.com/user/repo.git
cd repo.git
复制粘贴脚本,并根据你的信息修改以下变量:
旧的Email地址
,正确的用户名
,正确的邮件地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
git filter-branch --env-filter '
OLD_EMAIL="旧的Email地址"
CORRECT_NAME="正确的用户名"
CORRECT_EMAIL="正确的邮件地址"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags按
Enter键
执行脚本。用
git log
命令看看新 Git 历史有没有错误把正确历史 push 到 Github
1
git push --force --tags origin 'refs/heads/*'
删掉刚刚临时创建的 clone
1
2cd ..
rm -rf repo.git
git配置用户名和密码
修改:
1 | git config --global user.name "Your_Username" |
查看:
1 | git config user.name |
git白名单
在.gitignore
文件中如下配置,可以忽略除了lapsvmp_v02/gui/*.mat
下的所有.mat
文件。
1 | *.mat |
git分支重命名
假设分支名称为oldName,想要修改为 newName
1. 本地分支重命名(本地还没有推送到远程时)
1 | git branch -m oldName newName |
2. 远程分支重命名 (已经推送远程-假设本地分支和远程对应分支名称相同)
a. 重命名远程分支对应的本地分支
1 | git branch -m oldName newName |
b. 删除远程分支
1 | git push --delete origin oldName |
c. 上传新命名的本地分支
1 | git push origin newName |
d.把修改后的本地分支与远程分支关联
1 | git branch --set-upstream-to origin/newName |
Tag
切换到tag
git clone 整个仓库后使用,以下命令就可以取得该 tag 对应的代码了。
1 | git checkout tag_name |
但是,这时候 git 可能会提示你当前处于一个“detached HEAD” 状态。因为 tag 相当于是一个快照,是不能更改它的代码的。如果要在 tag 代码的基础上做修改,你需要一个分支:
1 | git checkout -b branch_name tag_name |
这样会从 tag 创建一个分支,然后就和普通的 git 操作一样了。
查看tag
1 | # 列出 tag |
创建tag
1 | 为本地仓库当前提交创建tag |
推送tag到远程服务器
1 | 推送指定tag |
删除tag
1 | 删除本地tag |
tag与commit
查看某个commit是否有对应的tag
1 | git describe --exact-match <commit-id> |
If what you want is the first tag containing the commit then:
1 | git describe --contains <commit> |
gives you all of the tags that contain that commit.
1 | git tag --contains <commit> |
tag中间的commit, 推荐下面的方式1
1 | git log --pretty=format:"%h; author: %cn; date: %ci; subject:%s" 11.0.211...11.0.212 |
git瘦身
有的时候经常将大文件添加到了git仓库,并且提交了,这个时候就需要重写存储库会删除不需要的历史记录,从而使存储库更小。 git filter-repo是用于快速重写Git存储库历史记录的工具,用法可以点击这里。
首先,安装插件:
1 | pip3 install git-filter-repo |
然后查看top 100 大文件:
1 | git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -100 | awk '{print $1}')" |
大文件多数集中在Pods文件夹内,移除Pods记录:
1 | git filter-repo --path-glob 'YMMCargoModule/Pods/*' --invert-paths --force |
这个时候,本地仓库就重写完毕了,需要提交到github:
1 | git push origin master --force |
可以发现,所有的提交记录都存在,但是仓库大小变小了。
过滤git log的提交历史
格式化提交输出只是 git log
其中的一个用途。另一半是理解如何浏览整个提交历史。接下来的文章会介绍如何用 git log
选择项目历史中的特定提交。所有的用法都可以和上面讨论过的格式化选项结合起来。
按数量
git log
最基础的过滤选项是限制显示的提交数量。当你只对最近几次提交感兴趣时,它可以节省你一页一页查看的时间。
你可以在后面加上 -<n>
选项。比如说,下面这个命令会显示最新的 3 次提交:
1 | git log -3 |
此时的日期是比较难看的,不同时区的人也没有统一,想要format日期
1 | --date=format:'%Y-%m-%d %H:%M:%S' # committer's timezone |
按日期
如果你想要查看某一特定时间段内的提交,你可以使用 --after
或 --before
标记来按日期筛选。它们都接受好几种日期格式作为参数。比如说,下面的命令会显示 2014 年 7 月 1 日后(含)的提交:
1 | git log --after="2014-7-1" |
你也可以传入相对的日期,比如一周前("1 week ago"
)或者昨天("yesterday"
):
1 | get log --after="yesterday" |
你可以同时提供--before
和 --after
来检索两个日期之间的提交。比如,为了显示 2014 年 7 月 1 日到 2014 年 7 月 4 日之间的提交,你可以这么写:
1 | git log --after="2014-7-1" --before="2014-7-4" |
注意 --since
、--until
标记和 --after
、--before
标记分别是等价的。
按作者
当你只想看某一特定作者的提交的时候,你可以使用 --author
标记。它接受正则表达式,返回所有作者名字满足这个规则的提交。如果你知道那个作者的确切名字你可以直接传入文本字符串:
1 | git log --author="John" |
它会显示所有作者叫 John 的提交。作者名不一定是全匹配,只要包含那个子串就会匹配。
你也可以用正则表达式来创建更复杂的检索。比如,下面这个命令检索名叫 Mary 或 John 的作者的提交。
1 | git log --author="John\|Mary" |
注意作者的邮箱地址也算作是作者的名字,所以你也可以用这个选项来按邮箱检索。
如果你的工作流区分提交者和作者,--committer
也能以相同的方式使用。
按提交信息
按提交信息来过滤提交,你可以使用 --grep
标记。它和上面的 --author
标记差不多,只不过它搜索的是提交信息而不是作者。
比如说,你的团队规范要求在提交信息中包括相关的issue编号,你可以用下面这个命令来显示这个 issue 相关的所有提交:
1 | git log --grep="JRA-224:" |
你也可以传入 -i
参数来忽略大小写匹配。
按文件
很多时候,你只对某个特定文件的更改感兴趣。为了显示某个特定文件的历史,你只需要传入文件路径。比如说,下面这个命令返回所有和 foo.py
和 bar.py
文件相关的提交:
1 | git log -- foo.py bar.py |
--
告诉 git log
接下来的参数是文件路径而不是分支名。如果分支名和文件名不可能冲突,你可以省略 --
。
按内容
我们还可以根据源代码中某一行的增加和删除来搜索提交。这被称为 pickaxe,它接受形如 -S"<string>"
的参数。比如说,当你想要知道 Hello, World!
字符串是什么时候加到项目中哪个文件中去的,你可以使用下面这个命令:
1 | git log -S "Hello, World!" |
如果你想用正则表达式而不是字符串来搜索,你可以使用 -G"<regex>"
标记。
这是一个非常强大的调试工具,它能让你定位到所有影响代码中特定一行的提交。它甚至可以让你看到某一行是什么时候复制或者移动到另一个文件中去的。
按范围
你可以传入范围来筛选提交。这个范围由下面这样的格式指定,其中 <since>
和 <until>
是提交的引用:
1 | git log <since>..<until> |
这个命令在你使用分支引用作为参数时特别有用。这是显示两个分支之间区别最简单的方式。看看下面这个命令:
1 | git log master..feature |
其中的 master..feature
范围包含了在 feature 分支而不在 master 分支中所有的提交。换句话说,这个命令可以看出从 master 分支 fork 到 feature 分支后发生了哪些变化。
diff
git diff
默认使用myers算法,该算法的原理可以参考Git 是怎样生成 diff 的:Myers 算法。
若想要直接对比两个文件,可以添加参数--no-index
,
1 | # git diff --no-index a b |
直接使用git diff
比较的时候,通常会在首部和尾部添加未更改的三行,若想只得到没有更改过的行,可以使用--unified
参数,
1 | git diff --no-index ori.cpp add.cpp --unified=0 |
git某个人或者某个组织的全部代码
不管在Linux上或者Windows上,都可以使用下面代码:
1 | CNTX={users|orgs}; NAME={username|orgname}; PAGE=1 |
- 设置
CNTX=users
andNAME=yourusername
,下载yourusername
的所有代码 - 设置
CNTX=orgs
andNAME=yourorgname
,下载yourorgname
的所有代码 - 设置
PAGE=num
,最大页面大小是100,因此您必须多次调用它才能获得所有存储库,此时下载第num
的所有代码。
但是若这样设置,可能会报错{"message":"API rate limit exceeded for 203.205.141.118. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)","documentation_url":"https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting"}
,此时可以在curl
后面加上-u your-username
,其中your-username
是你的github账户,并且会提示你输入对应的代码。
举个例子,比如git clone zdaiot
的所有代码:
1 | CNTX=users; NAME=zdaiot; PAGE=1 |
再比如,git clone apple
组织的所有代码:
1 | CNTX=orgs; NAME=apple; PAGE=1 |
status显示中文
status查看有改动但未提交的文件时总只显示数字串,显示不出中文文件名,非常不方便。比如:
1 | On branch hexo |
原因:在默认设置下,中文文件名在工作区状态输出,中文名不能正确显示,而是显示为八进制的字符编码。
解决办法:将git 配置文件 core.quotepath 项设置为false,quotepath表示引用路径,加上—global表示全局配置
git bash 终端输入命令:
1 | git config --global core.quotepath false |
merge错误
当远程有文件test.py
,本地有未跟踪的文件test.py
,此时使用git pull
更新本地仓库时,可能出现error: The following untracked working tree files would be overwritten by merge:
。
解决方法:
1 | git fetch origin |
error: src refspec master does not match any
一般有两个原因
原因1:没有提交过
Maybe you just need to commit. I ran into this when I did:
1 | mkdir repo && cd repo |
Oops! Never committed!
1 | git push -u origin master |
All I had to do was:
1 | git commit -m "initial commit" |
原因2:分支名字错误
Try git show-ref
to see what refs you have. Is there a refs/heads/master
?
Due to the recent “Replacing master with main in GitHub” action, you may notice that there is a refs/heads/main
. As a result, the following command may change from git push origin HEAD:master
to git push origin HEAD:main
所以得看下现在分支名字是什么,有可能是git push origin main
参考
git pull遇到错误:error: Your local changes to the following files would be overwritten by merge:
解决.gitignore文件忽略规则无效git依然跟踪修改的问题
github上的版本和本地版本冲突的解决方法
it 提示fatal: remote origin already exists 错误解决办法
nano命令
fatal: The current branch master has no upstream branch
git 查看远程分支、本地分支、创建分支、把分支推到远程repository、删除本地分支
git 如何让单个文件回退到指定的版本
【git】强制覆盖本地代码(与git远程仓库保持一致)
How to delete remote branches in Git
为什么Github没有记录你的Contributions
github多账号如何切换? - Tyrael.Liu的回答 - 知乎
关于gitignore:Git中的白名单和子目录
git修改分支名称
git切换到某个tag
Git瘦身
git pull报错: The following untracked working tree files would be overwritten by merge:
Message ‘src refspec master does not match any’ when pushing commits in Git
How to clone all repos at once from GitHub?
Github API: Fetch issues with exceeds rate limit prematurely
5.3 Git log 高级用法
git push 所有分支
How to change Git log date formats
git tag命令常用用法整理
How to find the tag associated with a given git commit?
—distributed-even-if-your-workflow-isnt
git status 显示中文和解决中文乱码