And that’s all you really need to know to start rebasing your branches. If you would prefer a clean, linear history free of unnecessary merge commits, you should reach for git rebaseinstead of git merge when integrating changes from another branch.

On the other hand, if you want to preserve the complete history of your project and avoid the risk of re-writing public commits, you can stick with git merge. Either option is perfectly valid, but at least now you have the option of leveraging the benefits of git rebase.

假设我们有如下图一所示仓库,该仓库有master和develop两个分支,且develop是在(3.added merge.txt file)commit处从master拉出来的分支。
image.png

merge工作原理

假设现在HEAD在(6.added hello.txt file)处,也就是在master分支最近的一次提交处,此时执行git merge develop, 结果如下图所示。
image.png

工作原理就是:git 会自动根据两个分支的共同祖先即 (3.added merge.txt file)这个 commit 和两个分支的最新提交即 (6.added hello.txt file) 和 (5.added test.txt file) 进行一个三方合并,然后将合并中修改的内容生成一个新的 commit,即图二的(7.Merge branch ‘develop’)。
这是merge的效果,简单来说就合并两个分支并生成一个新的提交。

rebase工作原理

git-rebase - Reapply commits on top of another base tip

那rebase是这么工作的呢?
假设初始状态也是图一所显示的。两个分支一个master,一个develop,此时HEAD在(6.added hello.txt file)处,现在执行git rebase develop,结果如下图三所示。
image.png
可以看见develop分支分出来分叉不见了,下面来解释一下它的工作原理:

在执行git rebase develop之前,HEAD在(6.added hello.txt file)处,当执行rebase操作时,git 会从两个分支的共同祖先 (3.added merge.txt file)开始提取 当前分支(此时是master分支)上的修改,即 (6.added hello.txt file)这个commit,再将 master 分支指向 目标分支的最新提交(此时是develop分支)即(5.added test.txt file) 处,然后将刚刚提取的修改应用到这个最新提交后面。如果提取的修改有多个,那git将依次应用到最新的提交后面

如下两图所示,图四为初始状态,图五为执行rebase后的状态。
image.png

image.png
简单来说,git rebase提取操作有点像git cherry-pick一样,执行rebase后依次将当前的提交cherry-pick到目标分支上,然后将在原始分支上的已提取的commit删除

总结

如果用一句话来描述 git rebase 和 git merge的最大区别,那就是: 两种合并所产生的log不一样。
image.png
image.png
从上图中看,rebase与merge的区别有些体现了,即它们产生的log tree不一样。我们放大这种效果再看
image.png
我们的分支模型最简单实用的,无外乎分支开发/主干合并。每当我们需要开发一个新特性时,就会创建一个特性分支。

  1. 当使用merge时,最后合产生的log随着特性分支的增多,log tree显得非常凌乱(其实也不凌乱,只是对比rebase模式而言)。
  2. 当使用rebase时,最后产生的log tree会成一条线,而依然能够清晰看出特性分支,图中黄色圈起来的地方。这是与merge的最大区别。
  3. 当然还有其它的不同a. 比如merge合并时会产生一个多余的节点(有些人认为这个节点没有任何意义,其实这代表了合并,怎么会没有意义呢?) 。b. 再比如rebase 在合并冲突时,可能没有merge好用(rebase会根据时间来diff,比如master 改了文件1某个地方,commit了,dev 改了文件1同一处,commit了,dev 又改了文件1同一处, commit了。此时期望的是dev最后1次commit的与master commit的 diff就行了,但是rebase还得diff多次
  4. rebase 最好不用于公共分支等我们就不讨论了。rebase与merge的具体实战操作并不难,就不作演示了。

    参考