Git rebase与merge的区别
Git场景
在基于Git版本控制的团队协作开发中,当同伴先于自己将新的提交push到远程分支上时,如果要想将自己新的提交push的远程分支,则需要先执行git pull
来获取同伴的提交,如果有冲突则先处理完冲突,然后才能将自己的提交push到远程分支。这种情形是非常常见的。
然而执行git pull
,在默认情况下,如果远程分支与本地分支的提交线图有分叉(即不是fast-forward
,如上述这种情形),git会执行一次merge操作(即相当于执行了git pull --merge
),而这会产生一次没有意义的提交记录。久而久之,项目的提交线图会非常混乱,其中会有很多由merge生成的无意义提交。
解决方案
为了避免这种情况的出现,在将提交push到远程分支之前,我们一般会执行如下命令:
1
$ git pull --rebase
分析对比
这时候,我们可能就会想:既然merge操作会生成无意义的提交,那它是不是没有什么价值了呢?是不是任何场景下都应该使用rebase操作?
所以,我们对rebase和merge进行分析和对比。了解清楚了两者的区别,我们才能更好地运用这两个策略。
场景设想
假设在执行pull之前的提交线图如下所示:
Merge操作
如果执行git pull
(git默认会执行git pull --merge
),提交线图会变成如下所示:
分析
提交线图中多出了一个没有必要的提交H
Rebase操作
如果执行git pull --rebase
,提交线图会变成如下所示:
分析
提交线图中,本地的新提交F
,G
变成了两个新的提交F'
,G'
,拼接在了C
后面,多余的分叉也删除了。提交线变得非常清晰。
小结
从上述对比可以看出,rebase操作会将本分支的新提交删除并生成新的提交。所以rebase操作比较适用于将一些零碎的提交进行合并清理。比如:在push之前进行整理。
那么merge操作意义何在呢?
merge操作与rebase操作相反,它可以保留了提交线图的分叉,并生成一个新的提交。这种场景适合用于大的分支合并。这样,我们可以在提交线图中看到项目开发迭代过程中经历过哪些feature分支等等。
注意
如果执行merge操作之前,提交线图是分叉的(即不是fast-forward
,如场景设想的情形),执行git merge
操作,是会达保留分支的目的。
但是执行merge操作之前,提交线图不是分叉的(即是fast-forward
,如下上图所示),此时执行git merge
操作的效果如下下图所示,分支是不会保留的。
在fast-forward
情况下进行合并,我们需要执行如下命令来保留分支。执行后的提交线图如下所示。
1
$ git merge --no-ff
(完)