rebase 的意义,就是对一个分支做「变基」操作。
常用的场景:
Rebase 场景一:合并多个commit提交;
1.我们来合并最近的 4 次提交纪录,执行:
git rebase -i HEAD~4
这时候,会自动进入 vi 编辑模式:
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)
2.按照如上命令来修改你的提交纪录:
p b4d5768 add b.php
s b4d5768 add b.php
s b4d5768 add b.php
3.如果保存的时候,你碰到了这个错误:
error: cannot 'squash' without a previous commit
你可以输入git rebase --edit-todo
重新进入vim编辑
编辑完然后输入git rebase --continue
继续变基操作;
Rebase 场景二:分支合并
假设你在一个mywork分支上开发;mywork是从master分支创建的;
(master分支)
git checkout -b mywork
之后,当你的同事要紧急修改master分支,他拉了一个hotfix分支,然后将更改后的分支提交到master分支,
那你本地的分支是不是就落后于master的分支;如下图;
你本地的mywork分支指向C6节点,origin分支指向C4节点(C4节点由C3节点和hotfix合并后生成);
现在需要变基操作来整合两个分支:
Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase。
git merge 和git rebase的差异;
1、git merge
mywork分支与origin分支本地提交合并(merge)成版本C7,但这样会形成图中的菱形。
2、git rebase
重点来了:
git checkout mywork
git rebase origin
-
step 1:
mywork分支会把mywork分支之前的提交的信息(C5,C6)都消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到”.git/rebase“目录中),之后更新mywork分支跟当前的origin分支保持一致,然后把临时补丁(patch)用到”mywork“分支上。
-
step 2:
当’mywork‘分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除.
现在我们可以看一下用合并(merge)和用rebase所产生的历史的区别:
git merge和rebase的差异其实就是git pull 和 git pull --rebase的差异;
git pull 等于 git fetch ;git merge
git pull --reabase 等于 git fetch;git rebase
git rebase master
执行的具体操作如下:
首先,git 会把 feature1 分支里面的每个 commit 取消掉;
其次,把上面的操作临时保存成 patch 文件,存在 .git/rebase 目录下;
然后,把 feature1 分支更新到最新的 master 分支;
最后,把上面保存的 patch 文件应用到 feature1 分支上;
rebase是一个危险的操作,你和你的同事如果同事在一个分支上开发,当你rebase分支,你的同事pull的时候会发现少了很多提交信息,
如果你只对不会离开你电脑的提交执行变基,那就不会有事。 如果你对已经推送过的提交执行变基,但别人没有基于它的提交,那么也不会有事。 如果你对已经推送至共用仓库的提交上执行变基命令,并因此丢失了一些别人的开发所基于的提交, 那你就有大麻烦了,你的同事也会因此鄙视你。
核心思想:变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。 如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你还要拉取并整合他们修改过的提交,事情就会变得一团糟。
所以:尽量不要在公共开发的分支上做变基操作,这样很容易造成麻烦;