merge和rebase区别与项目中的选择

2,532 阅读3分钟

什么是rebase?

  • rebase就是re + base,re表示“重新”,base表示“基础”,即“变换基础”的意思
  • rebase从本质上讲就是变换一个或多个commit的基础,也就是上游commit,而用来做合并操作只是rebase的一种应用场景
  • rebase在变换一系列commit基础的同时,还让我们有机会去整理这些待rebase的commit,比如合并多个commit,修改某次commit等

这些就是rebase命令的本质,所以rebase和merge本身并不应该直接作为两种合并代码的方式来比较,正确认识rebase命令是一个很重要的前提

当然,本文主要从代码合并的场景来比较rebase和merge的区别

合并时的核心区别

rebase会改变提交历史;merge则会保留真实的历史

合并代码log图解

合并后可以看到真实的提交历史,merge后形成H这个新的合并提交(如果可快进合并则不会产生新的提交;如果可快进合并但在merge时使用了--no-ff,--no-ff是no fast forward的意思,也就是禁用快进式合并,则还是会产生一个新的合并提交;使用--no-ff好处是可以从历史记录清楚的看到做了一个合并操作,而不会因为快进合并导致历史成为一条线)

在topic上rebase master时,git会从topic的A、B、C复制出三个新的提交(原先的A、B、C之后会被git回收掉)依次添加到master上的G提交后(可能出现三次重复的冲突,思考下为什么?可以通过git rerere来解决,不展开说了),rebase完成后历史记录变成了一条线

合并时的其他区别

  • merge如果不能快进合并(fast forward),就会形成一个额外的合并提交;rebase不会形成新的合并提交(但会生成要rebase的一系列commit的副本来做变基)
  • rebase可用来整理待变基的一系列提交记录,比如合并多个提交等;merge没有这个功能

小结

merge相对可靠,而使用rebase要注意两点

  • 当对已push到远程的提交做rebase操作时,可能会造成远端的提交历史和其他人本地不一致(所以最好不要这么做,比如想合并多个commit成一个,要先确保这些commit没有push到远端)
  • rebase后看不到真实的历史记录了。这一点看团队规范,有的团队偏好用rebase做合并,因为合并后可以形成一条线性的历史记录,这样项目演进路线更清晰;但我个人建议用merge,虽然历史记录相对错综复杂但贵在真实,可以通过历史记录清楚的看到代码真实的演进过程,而从复杂的历史中剖析出我们需要的数据则是我们开发人员或者其他辅助工具应该在上层做的工作