在之前的文章当中我们介绍了git merge的用法,明白了通过git merge我们可以合并两个分支的改动。这样我们就可以很方便地进行协同开发了,每个人都在自己的分支下开发代码,开发完毕之后再一起合并到master分支。通过这种方式可以保证大家的代码不会陷入混乱,但是这样有一个隐含的缺陷。
缺陷就是我们之前说过的,当我们合并两个没有上下游关系的分支时,git会自动替我们生成一个merge commit,记录此次的merge。记录merge操作没有什么问题,问题是如果我们遇到特殊情况需要反复merge的时候,就会导致commit的提交记录非常混乱,你根本分不清什么是什么。尤其是当你merge了一个巨大改动的分支之后,你的git log基本上就不用看了,肯定全都是其他人的各种乱七八糟你也不清楚的提交记录。
为了解决这个头疼的问题,我们就需要用到rebase操作。
rebase简介
rebase是一个非常强大的操作,可以实现一些神奇的功能,但是强大也意味着有隐患,因为如果使用得不好可能给团队的代码造成非常大的问题,成为团队当中被无情指责的背锅侠。所以我们在使用之前一定要先了解清楚原理,之后再小心谨慎地使用,否则很有可能会产生问题。
首先说说rebase的功能,rebase的功能说白了可以提取我们在A分支上的改动,然后应用在B分支的代码上,完成类似于补丁的功能。我这么说非常空洞,我从learngitbranching.js.org网站上截取了一些图,会清晰一些。另外推荐一下这个网站,当中有一些图形化的演示和实操功能, 我们可以在上面练习我们学到的git命令加深印象。但是它也有一个缺点,就是一些细节介绍得比较少,这也是我没有一开始的时候就推荐给大家的原因。
这张图非常经典,是很多场景下的常态。C1是线上的版本,在C1的代码上线了之后我们发现了一个bug,于是我们checkout了一个叫做bugFix的分支。与此同时还有新的功能在开发,新的功能提交到了master之后形成了节点C2。这个时候我们在bugFix分支当然可以merge master这没有什么问题,但是也可以rebase master,rebase之后整棵git树会变成这样:
这个结果就好像是我们先到了C2然后checkout出了bugFix分支,然后在bugFix分支上将之前写过的代码重新写了一遍。这样的操作就是变基,当我们rebase了之后再提交合并请求我们的合并记录里面会非常干净,没有多余merge的信息。对于多人协同开发的场景非常有帮助。
更牛的例子
上面只是一个rebase操作的基本应用,通过rebase操作我们还可以实现更加炫酷的功能。我们来看这样一张提交图:
这张图也非常经典,master是正常的线上分支,在C2节点处代码上线。上线之后继续开发新的需求checkout了新的分支feature,与此同时master也经过了一些合并,合并了另外的一些改动到了C4节点。之后新的分支feature开发完成了一个重要性能提升的改动C5,这时,我们发现了线上代码的一个bug并且性能不佳,我们需要紧急修复。于是在C5处checkout了新的分支bugFix,我们在bugFix分支当中修复了bug,想要发布上线。
这时候feature分支继续开发到了C6节点,仍然没有开发完成,也没有经过系统测试。所以我们并不希望C6的代码发布上线,我们希望合并进入master的代码之后C5,C7和C8。我们只需要在bugFix分支rebase到master,然后修复冲突之后提交。提交完成了之后,我们再checkout到master把bugFix分支merge进来。整个流程如下:
git checkout bugFix
git rebase master
git checkout master
git merge bugFix
后我们得到的结果会是这样:
我们继续问一个问题,假如我们只需要合并bugFix分支自己的改动,不希望把C5节点也合并进来,我们应该怎么办?如果不用rebase会非常麻烦,我们很难处理。有了rebase之后非常简单,我们只需要使用onto参数,它可以限制我们rebase从什么地方开始。
比如我们希望rebase的内容是在bugFix这个分支当中不在feature分支里的内容,我们可以这么写:
git rebase --onto master feature bugFix
git执行这条命令的时候会先找到feature和bugFix的共同祖先,然后将共同祖先之后的部分rebase到master。
还有一个问题是如果我们要把两个分支合并进master,我们要rebase merge两次不免有些麻烦,我们也可以这么操作。比如我们要把刚才说的feature和bugFix都merge进来,我们可以直接执行git rebase master feature,它会先checkout到feature分支然后执行rebase master的操作,之后我们再checkout到master进行合并即可。也就是说我们在命令当中可以把要执行的执行分支和目标分支都写出来,这样可以一步到位。
比如我现在在master分支,我执行git rebase master bugFix之后会变成这样:
比我们自己一条一条命令写会方便很多。
总结
简单总结一下,我们使用rebase命令有很多好处,既可以让merge操作变得顺滑,减少没有意义的commit记录。也可以实现一些比较棘手的功能,但对于新手来说,这个功能还是比较陌生的,总是会觉得晕不知道自己到底做了什么。这也是非常正常的,我们可以在learngit这个网站上实际动手试试,多练习一下,这个网站的提交都是虚假的,怎么玩都不会出问题,总比我们在实际工作当中拿真实的代码来演练要好。
在下一篇文章当中我们将会一起来看看git rebase不能做什么,可能有的隐患。
今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、在看、转发)
- END -