@captainjack
2021-04-14T06:53:50.000000Z
字数 4382
阅读 372
git
如果你准备从git新手向更高级一点的目标学习的话,那么你应该认真的学习一下git rebase命令.这个命令可以让你对应git commit history管理更加得心应手.本文主要从工作实际应用出发,分三个部分:
1. git rebase 简介
2. git rebase 与 git merge 的区别
3. git rebase -i (交互式rebase)
rebase,翻译成中文叫变基
,这个很好理解,base就是基础
的意思,rebase自然就叫变基
,那拆开来就是改变基础
的意思,那再想一下,在git中,基础指什么?当然是git commit 历史,所以简单理解起来,git rebase命令就是用来改变git commit历史的.
在git中整合来自不同分支的修改主要有两种方法:merge
和rebase
.我们通过一个实际的场景来说明两者的区别.看下图:
如果,我们有两个分支,开发分支experiment
和主分支master
,两个分支都有各自的更新c4
和c3
,这个时候我们如果用git merge命令.那么得到的效果如下图:
可以看到,它会把两个分支的最新快照(C3 和 C4)以及二者最近的共同祖先(C2)进行三方合并,合并的结果是生成一个新的快照(并提交),这里强调一下,我们产生了一个新的提交!!!
那么,如果我们用git rebase会怎么样呢? 试一下
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
结果如下图:
提取在 C4
中引入的补丁和修改,然后在 C3
的基础上应用一次,在 Git 中,这种操作就叫做rebase
/变基
,它的原理是首先找到这两个分支(即当前分支 experiment
、变基操作的目标基底分支 master
)的最近共同祖先 C2
,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目标基底C3
, 最后以此将之前另存为临时文件的修改依序应用。这里注意观察一下,并没有产生多的提交!!!
这时候,再回到master
分支,进行一次fast-forward(快进)
合并
$ git checkout master
$ git merge experiment
得到的最终结果如下:
看起来是不是 特别干净!!!
这个大概是 git merge 跟 git rebase 在使用中的区别
很多时候,我们需要修改某个分支的提交历史,这个时候,就需要用到git rebase -i
。
用法如下
git rebase -i 需要改变的commit的前一个commit号
来看一个实际的例子
你想要修改最近三次提交信息,或者那组提交中的任意一个提交信息,将想要修改的最近一次提交的父提交作为参数传递给 git rebase -i 命令,即 HEAD~2^ 或 HEAD~3。 记住 ~3 可能比较容易,因为你正尝试修改最后三次提交;但是注意实际上指定了以前的四次提交(因为当前提交是HEAD~0),即想要修改提交的父提交。这里是我觉得可能会绕一点的,建议慢点看。
于是,输入命令
$ git rebase -i HEAD~3
得到
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
你可以看到上面的输出,一个提交列表,可以使用vim进行编辑,不懂vim的看这里
这里,主要提醒注意两点:
1. 你看到的上面三个commit记录的顺序,跟你使用git log
看到的顺序是反的。
2. 对应的commands 都有相应的英文解释,自己先看明白了
下面我们针对每个command 进行讲解:
* pick
,就是会保留这个commit,什么都不变,不变顺序,也不变commit信息
* reword
,就是只改变commit信息
* edit
,相当于对这个commit 使用 git commit --amend
* squash
,压缩这个commit,就是把对应更改压缩到前一次提交,去掉本次提交,但是这次的提交信息还保留着
* fixup
,这个比较squash
,就是提交信息也不保留了
* exec
,这个我没用过,应该是执行shell 命令吧直接,暂时不会用到
有可能,你看到这里还是有点蒙蔽,下面我们直接来说说,下一步我们可以做哪些事情
1. 改变提交顺序
还记得之前列出来的3次提交吧,你可以通过文本编辑,直接删除或者交换顺序
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
比如我们可以删除 added cat-file
这次提交,并且交换另外两次提交的顺序,
像这样
pick 310154e updated README formatting and added blame
pick f7f3f6d changed my name a bit
然后,你保存并退出文本编辑,最后你看到的结果就是,git 修改了提交顺序并且移除了你刚才删除的提交
2. 压缩提交
继续回到那三次提交
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
如果我们想要压缩310154e
和a5f4a0d
这两次提交,那么我们就需要用之前提到的命令squash
或者fixup
,通常我们用squash
,提交信息嘛,待会也是可以注释删除掉的
我们编辑文本如下:
pick f7f3f6d changed my name a bit
squash 310154e updated README formatting and added blame
squash a5f4a0d added cat-file
这个时候,保存并推出文本编辑器,Git会应用这三次修改,然后再把你放到编辑器中来合并三次提交信息(之前就跟你说squash也可以注释来删除提交信息),你看到的编辑器是这样的:
# This is a combination of 3 commits.
# The first commit's message is:
changed my name a bit
# This is the 2nd commit message:
updated README formatting and added blame
# This is the 3rd commit message:
added cat-file
这还有啥好说的,看看你想要提交信息是什么样子的,就编辑成什么样子呗,注意一下 #
开头的,就是相当于注释掉,然后一样的操作,保存并推出,你就完成了压缩提交操作:)
3. 拆分提交
这个就有点意思了,感觉之前の命令里面,好像没有说到可以拆分提交的.没有说就等于没有吗?那你就太年轻了.下面来看一下,我们怎么做到的
还是回到那三次提交
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
这时候,我们想要把310154e
拆分成,updated README formatting和added blame,那么我们可以对310154e
提交试用edit
命令,像这样
pick f7f3f6d changed my name a bit
edit 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
保存并推出文本编辑器.
然后你看到提示信息如下,并且进入到命令行
Stopped at 310154e... changed my name a bit
You can amend the commit now, with
git commit --amend
Once you’re satisfied with your changes, run
git rebase --continue
上面说,你可以选择git commit --amend
或者git rebase --continue
,前者是修改本次提交,后者是继续下一步. emmm,那我们现在改怎么做呢?
我们选择做自己想做的,撤销本次提交,然后将修改的内容分两次提交
像这样:
$ git reset HEAD^
$ git add README
$ git commit -m 'updated README formatting'
$ git add lib/simplegit.rb
$ git commit -m 'added blame'
最后在执行
git rebase --continue
完成之后,你看到的提交历史就是这样的
$ git log -4 --pretty=format:"%h %s"
1c002dd added cat-file
9b29157 added blame
35cfb2b updated README formatting
f3cc40e changed my name a bit
显然,我们完成了对历史提交的拆分,欧耶~
那么,你现在大概知道了 git rebase的用法,多用几次就熟悉了,其实最主要的就是,你现在可以用这个方法来整理你的提交历史,让你的提交显得清晰,不冗余.
暂时先写到这里
参考资料:
1.git-book,分支-变基
2.git-book,工具-重写历史