Git常用命令

目录

基本操作

分支及合并相关

撤销/放弃本地修改

使用git reset或git revert回退版本

使用git stash暂存更改

使用git diff打补丁

本地分支和远程分支建立追踪关系的三种方式

分支拉取与推送

打标签以及推送标签

从HTTP方式换成SSH方式

常见场景


基本操作

(1)添加文件到Git仓库,分两步:

添加到暂存区:

git add <file> # 可反复多次使用,添加多个文件
git add . # 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
git add -A # 提交所有变化
git add -u # 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new)

提交到仓库:    

git commit -m "message"
git commit -am "message"
相当于
git add .
git commit -m "message"

 (2)要随时掌握工作区的状态,使用git status命令。如果git status告诉你有文件被修改过,用git diff可以查看修改内容。

(3) HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

(4)命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。

git log --graph --pretty=oneline --abbrev-commit命令可以看到分支合并图。

git log --pretty="%h [%an-%cn-%cd] - %s" --author='alan' . 查看当前分支下,对当前目录下文件有过修改的提交历史,指定输出格式,过滤条件(参考2.3 Git 基础 - 查看提交历史)

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

(5)查看远程库信息,使用git remote -v

(6) 通过 git blame 找到文件的修改者

git blame <file_path>   # 查看某个文件的每一行内容由谁所写
git blame <file_path> | grep "<keyword>"   # 只查文件中某一部分由谁所写
git blame <file_path> -L a,b  # -L 参数表示后面接的是行号(Line),  a,b代表查询文件的第a行到第b行之间的文件内容情况。
                                             # a, 则代表从第a行到文件结尾
                                             # ,b 则代表从文件开头到第b行

(7) git show <commit_id> 查看提交记录详情

(8) git log --oneline origin/master..feature/localization

git log --oneline dev ^master # 查看dev有,而master中没有的
git log --oneline master ^dev # 查看master有,而dev中没有的
git log --oneline master..dev # 查看dev中比master中多提交了哪些内容
git log --oneline dev..master # 查看master中比dev中多提交了哪些内容

分支及合并相关

本地新建的分支如果不推送到远程,对其他人不可见

查看分支:git branch

查看上游分支的名字:git branch -vv

创建分支:git branch <branch-name>

备份当前分支(以时间命名backup/201231):git branch backup/$(date +%y%m%d)

切换分支:git checkout <branch-name>

创建+切换分支:git checkout -b <branch-name> # 相当于git branch <branch-name> + git checkout <branch-name>

创建+切换分支+指定上游分支:git checkout -b <branch-name> origin/master# 相当于git branch <branch-name> + git checkout <branch-name> + git branch -u origin/master

删除分支:git branch -d <branch-name>

强行删除分支:git branch -D <branch-name>

重命名当前分支:git branch -m <new-branch-name>

重命名非当前分支:git branch -m <old-branch-name> <new-branch-name>

合并某分支到当前分支:git merge <branch-name>

 

Git自动合并分支条件

1、修改不同的文件

2、修改相同文件的不同区域

3、同时更改文件名和文件内容

合并分支时出现冲突

当Git无法自动合并分支时,就必须首先解决冲突,解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,解决冲突后,再提交,合并完成。

git merge --abort # 取消合并

撤销/放弃本地修改

1、未使用 git add 缓存代码时:

git checkout -- <path/to/file> # 放弃某个文件的修改,--可以省略
git checkout . # 放弃所有文件的修改

此命令用来放弃掉所有还没有加入到缓存区的修改(内容修改与整个文件删除),但是此命令不会删除掉刚新建的文件,因为刚新建的文件还没已有加入到 git 的管理系统中,所以对于git是未知的,自己手动删除就好了 。

2、 已经使用 git add 缓存代码,但还没提交时:

git reset HEAD <path/to/file> # 放弃指定文件的缓存
git reset HEAD . # 放弃所有文件的缓存

此命令用来清除 git  对于文件修改的缓存,相当于撤销 git add 命令所在的工作。在使用本命令后,本地的修改并不会消失,而是回到了如(1)所示的状态,继续用(1)中的操作,就可以放弃本地的修改。 

3、已经用 git commit 提交了代码时 :

git reset HEAD^ # 回退到上一版本,但工作区保留当前版本和退回版本的变动
git reset --hard HEAD^ # 回退到上一版本,但工作区不保留当前版本和退回版本的变动
git reset <commit id> # 回退到以前任意版本,但工作区保留当前版本和退回版本的变动
git reset --hard <commit id> # 回退到以前任意版本,但工作区不保留当前版本和退回版本的变动

 

使用git reset或git revert回退版本

git reset的作用是修改HEAD的位置,即将HEAD指向的位置改变为之前存在的某个版本。如果想恢复到之前某个提交的版本,且那个版本之后提交的版本我们都不要了,就可以用这种方法。

git reset --hard <commit id>

git revert是用于“反做”某一个版本,以达到撤销该版本的修改的目的。如果我们想撤销之前的某一版本,但是又想保留该目标版本后面的版本,记录下这整个版本变动流程,就可以用这种方法。 

git revert <commit id>

使用 git revert <commit> 可以撤销指定的提交, 如果要撤销一串提交可以用 <commit1>..<commit2> 语法。 注意这是一个前开后闭区间,即不包括 commit1,但包括 commit2。注意 revert 命令会对每个撤销的 commit 进行一次提交,--no-commit 后可以最后一起手动提交。

git revert --no-commit <commit1>..<commit2>

使用git stash暂存更改

(1)git stash save "save message":执行存储时,添加备注,方便查找,只有git stash 也要可以的,但查找时不方便识别。

(2)git stash list:查看stash了哪些存储

(3)git stash show:显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{$num},比如第二个 git stash show stash@{1}

(4)git stash show -p:显示第一个存储的改动,如果想显示其他存存储,命令:git stash show  stash@{$num}  -p ,比如第二个:git stash show  stash@{1}  -p

(5)git stash apply:应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{$num} , 比如第二个:git stash apply stash@{1} 

(6)git stash pop:命令恢复之前缓存的工作目录,将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下,默认为第一个stash,即stash@{0},如果要应用并删除其他stash,命令:git stash pop stash@{$num} ,比如应用并删除第二个:git stash pop stash@{1}

(7)git stash drop stash@{$num}:丢弃stash@{$num}存储,从列表中删除这个存储

(8)git stash clear删除所有缓存的stash

新增的文件,由于没有在git版本控制中,直接执行git stash是不会被存储的,需要先执行git add加到git版本控制中,然后再git stash。

使用git diff打补丁

一、生成补丁

1、比较工作区与暂存区

git diff # 不加参数即默认比较工作区与暂存区
git diff > patch # patch的命名是随意的,如 git diff > ~/Desktop/test.diff

2、比较暂存区与最新本地版本库(本地库中最近一次commit的内容)

git diff --cached > patch

3、比较工作区与最新本地版本库

git diff HEAD > patch # 如果HEAD指向的是master分支,那么HEAD还可以换成master
git diff --HEAD > patch

4、比较工作区与指定commit-id的差异

git diff commit-id > patch

5、比较暂存区与指定commit-id的差异

git diff --cached [<commit-id>] > patch

6、比较两个commit-id之间的差异

git diff [<commit-id>] [<commit-id>] > patch

7、将单个文件做成一个单独的补丁

git diff file_name > patch

 二、应用补丁

git apply patch

应用补丁之前可以先检验一下补丁能否应用,如果没有任何输出,那么表示可以顺利接受这个补丁。

git apply --check patch

另外可以使用git apply --reject patch将能打的补丁先打上,有冲突的会生成.rej文件,此时可以找到这些文件进行手动打补丁。

本地分支和远程分支建立追踪关系的三种方式

1、手动建立追踪关系

git branch --set-upstream-to=<远程主机名>/<远程分支名> <本地分支名>

如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用该命令建立追踪关系。

2、push时建立追踪关系

git push -u <远程主机名> <本地分支名>

加上-u参数,这样push时,本地指定分支就和远程主机的同名分支建立追踪关系。

3、新建分支时建立跟踪关系

git checkout -b <本地分支名> <远程主机名>/<远程分支名>

本地和远程分支的名称最好一致。新分支指针指向 <远程主机名>/<远程分支名> 所指的位置。具体位置可用 git log --oneline --graph 查看。

注意:使用 1 和 3 命令前要先确保本地有名为 <远程主机名>/<远程分支名> 的远程跟踪分支,没有就要先用 git fetch 或 git pull 命令从远程主机上抓取,抓取后自动产生。远程跟踪分支是远程分支状态的引用, 它们是你不能移动的本地引用。用 git branch 看不到,用 git branch -r 才可以看到。

查看追踪关系

git branch -vv

输出:

  dev    4b89ec4 [origin/dev] output user name
* master 8382f8d [origin/master: ahead 1] output age

这里可以看到 dev 分支正在跟踪 origin/dev 分支并且是最新的,master 分支正在跟踪 origin/master 分支并且 “ahead”是1,意味着本地有1个提交还没有推送到服务器。

分支拉取与推送

一、git pull

git pull 实际上是两个命令合成了一个:git fetch 和 git merge。当我们从来源拉取修改时,我们首先是像 git fetch 那样取回所有数据,然后最新的修改会自动合并到本地分支中。

 

1、git pull命令的完整格式

git pull <远程主机名> <远程分支名>:<本地分支名>

作用是取回远程主机的指定分支,再与本地的指定分支合并。

2、省略本地分支名

git pull <远程主机名> <分支名>

当只有一个分支名时,这个分支名默认是远程分支名。作用是取回远程主机的指定分支,再与本地的当前分支合并。

例如:git pull origin dev,假设本地的当前分支是master。

结果:取回远程主机 origin 的 dev 分支与本地的当前分支,即与 master 分支合并。

3、当前分支与远程分支存在追踪关系(可能有多个追踪关系)

git pull <远程主机名>

取回远程主机与当前分支有追踪关系的分支,再与本地的当前分支合并。如果没有追踪关系使用该命令则会报错。

4、当前分支只有一个追踪关系

git pull

取回远程与当前分支有唯一追踪关系的分支,再与本地的当前分支合并。如果没有追踪关系使用该命令则会报错。

5、拉取远程主机上被他人rebase操作然后强制推送的分支

git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

有人推送了经过rebase操作的提交,并丢弃了你的本地开发所基于的一些提交,但是你push之后,那些被对方丢弃的提交又出现了,这是对方所不希望看到的。所以在拉取合并时加上 --rebase 选项,git内部会自动检测,合并的结果会丢弃一些提交,符合预期。若出现冲突,vim进去手动解决冲突,然后git add -u, git rebase --continue。

6、在本地删除远程主机上已删除的对应分支

git pull -p

如果在远程主机删除了某个分支,默认情况下,git pull 不会在拉取远程分支的时候,删除对应的本地分支。如果要删除,加上 -p 选项即可。

二、git push

1、git push命令的完整格式:

git push <远程主机名> <本地分支名>:<远程分支名>

git branch -vv
feature/foo     123456abcde [origin/feature/bar: ahead 2, behind 98] test
git push origin feature/foo:feature/bar

作用是将本地的指定分支推送到远程主机的指定分支上。

注意:git pull是<远程分支名>:<本地分支名>,而git push是<本地分支名>:<远程分支名>。

2、省略远程分支名

git push <远程主机名> <分支名>

当只有一个分支名时,这个分支名默认是本地分支名。作用是将本地的指定分支推送到远程主机的同名分支上。注意如果远程主机不存在该同名分支,则会自动新建同名分支。

例如:git push origin dev,假设本地的当前分支是master。

结果:将本地的 dev 分支推送到远程主机 origin 的 dev 分支上,和本地的当前分支是 master 没有关系。

3、省略本地分支名

git push <远程主机名> :<远程分支名>

如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支

在Git v1.7.0 之后,还可以使用下面这种语法删除远程分支:

git push <远程主机名> --delete <远程分支名>

4、当前分支与远程分支存在追踪关系(可能有多个追踪关系)

git push <远程主机名>

作用是将本地的当前分支推送到远程主机有追踪关系的对应分支上。如果没有追踪关系使用该命令则会报错。

5、当前分支与远程分支只有一个追踪关系

git push

作用是将本地的当前分支推送到远程有唯一追踪关系的对应分支上。如果没有追踪关系使用该命令则会报错。

6、建立追踪关系并指定默认远程主机

git push -u <远程主机名> <本地分支名>

作用是将本地的指定分支推送到远程主机的同名分支。另外因为加了-u参数,所以如果没有追踪关系则会建立,另外如果当前指定分支与多个远程主机存在追踪关系,则指定该远程主机为默认主机,后面就可以不加参数使用git push。

7、推送所有分支

git push --all <远程主机名>

不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用–all选项。如果远程主机的版本比本地版本更加新,推送时Git会报错,要求先在本地做git pull合并差异或解决冲突,然后再推送到远程主机。但是如果你一定要推送,可以使用下面的–force选项。

8、用本地所有分支覆盖远程所有分支

git push --force <远程主机名> # 不安全
git push --force-with-lease # 比 --force安全

使用–force选项,结果导致远程主机上的版本直接被覆盖。除非你很确定要这样做,否则应该尽量避免使用–force选项。

打标签以及推送标签

新建一个标签:

git tag <tagname> # 默认为HEAD,也可以指定一个commit id
git tag -a <tagname> -m "blablabla..." # 可以指定标签信息

查看所有标签:

git tag

查看标签信息:

git show <tagname>

删除一个本地标签

git tag -d <tagname>

推送一个本地标签到远程:

git push <远程主机名> <本地标签名>

推送本地全部未推送过的标签到远程:

git push <远程主机名> --tags

删除一个远程标签(即推送一个空的标签到远程标签):

git push <远程主机名> :refs/tags/<远程标签名>

在Git v1.7.0 之后,还可以使用下面这种语法删除远程标签:

git push <远程主机名> --delete tag <远程标签名>

从HTTP方式换成SSH方式

git remote add origin https://github.com/github-username/repo-name.git
remote -v
git remote remove origin
remote -v
git remote add origin git@github.com:github-username/repo-name.git
remote -v

拣选(Cherry-picking)

当一个特定分支包含我们的活动分支需要的某个提交时,我们对那个提交执行 cherry-pick!对一个提交执行 cherry-pick 时,我们会在活动分支上创建一个新的提交,其中包含由拣选出来的提交所引入的修改。

变基(Rebasing)

git rebase操作可以把本地未push的分叉提交历史整理成直线,rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。git rebase 会将当前分支的提交复制到指定的分支之上。

git rebase -i master合并多次提交

rebase to master

远端origin分支:origin/master,origin/feature/test

本地local分支:master,feature/test

1、git fetch #本地feature分支和远端feature分支同步

2、git rebase origin/master

如果有冲突,git status查看冲突的文件,打开改文件,会有current change和incoming change,current change为feature分支的文件内容,incoming change为master分支的文件的内容,解决冲突后保存,git add <冲突文件>,git rebase --continue,如果再有冲突,继续重复以上过程,直到解决所有冲突,rebase完成;如果放弃rebase,则git rebase --abort

3、git push --no-verify --force-with-lease origin feature/test 推送到远端

git push --no-verify --force-with-lease origin HEAD

Somtimes, the project might set the commit message guide line, if your commit doesn't meet the requirement, ghook will reject it. If you really not sure how to do that, you can use '--no-verify' to skip this check.

常见场景

1、

当接到修复bug任务时,但我们手头工作还没完成,先git stash把当前工作现场“储藏”起来;通过创建新的bug分支进行修复,然后合并,最后删除;bug修复后,再通过git stash pop,回到工作现场,恢复的同时把stash内容也删了。可以多次stash,恢复的时候,先用git stash list查看刚才的工作现场存到哪去了,然后用命令git stash apply stash@{0}恢复指定的stash,但是恢复后,stash内容并不删除,还需要用git stash drop来删除。

2、

多人协作的工作模式通常是这样:

        1、首先,可以试图用git push origin <branch-name>推送自己的修改;

        2、如果推送失败,则因为远程分支比你的本地更新,需要先用git pull抓取远程的新提交,试图合并;

        3、如果合并有冲突,则解决冲突,并在本地提交;

        4、没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!

3、代码太老,git pull很多冲突,转移diff

{

git pull 遇到很多冲突

git reset HEAD

git checkout .

或git add .并git commit -m "message"

或git stash

git checkout color_map

git log

}

git checkout feature/maploc

git pull

git checkout -b adjust_intensity

git branch -vv

git branch --set-upstream-to=origin/feature/maploc // 设置upstream

git branch -vv

git cherry-pick <commit_id_1>,git log确认

arc diff --create

git cherry-pick <commit_id_2>

出现冲突,git status查看并解决冲突,git add .,git cherry-pick --continue 

arc diff

git branch -D color_map

abandon color_map 对应的diff



Q&A

Q:

$ git pull
error: cannot lock ref 'refs/remotes/origin/xxx/yyy/zzz': unable to resolve reference 'refs/remotes/origin/xxx/yyy/zzz': reference broken
From <repo>
 ! [new branch]            xxx/yyy/zzz -> origin/xxx/yyy/zzz  (unable to update local ref)

A:

#方法1
git gc --prune=now
git remote prune origin
#方法2
git update-ref -d refs/remotes/origin/xxx/yyy/zzz
#方法3
rm .git/logs/refs/remotes/origin/xxx/yyy/zzz 

参考:

Git - Book

Git - Reference

Resolve Git merge conflicts in favor of their changes during a pull

工作流一目了然,看小姐姐用动图展示10大Git命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值