git merge 与 git rebase的区别

前言
其实这个问题困扰我有一段时间,相信也有人和我同样有这个困扰,网上已有不少这种解释了,可是要么就是无图,要么就是解释的很乱,没太看懂,通过本身对git的使用,加上向同事请教,算是理解了这个问题,因此写下来分享一下,我尽可能详细说明git

merge与rebase的区别
假设咱们有以下图一所示仓库,该仓库有master和develop两个分支,且develop是在(3.added merge.txt file)commit处从master拉出来的分支。 
 
图一
merge
假设如今HEAD在(6.added hello.txt file)处,也就是在master分支最近的一次提交处,此时执行git merge develop, 结果以下图所示。 
 
图二工具

工做原理就是:git 会自动根据两个分支的共同祖先即 (3.added merge.txt file)这个 commit 和两个分支的最新提交即 (6.added hello.txt file) 和 (5.added test.txt file) 进行一个三方合并,而后将合并中修改的内容生成一个新的 commit,即图二的(7.Merge branch ‘develop’)。 
这是merge的效果,简单来讲就合并两个分支并生成一个新的提交。
rebase
那rebase是这么工做的呢? 
假设初始状态也是图一所显示的。两个分支一个master,一个develop,此时HEAD在(6.added hello.txt file)处,如今执行git rebase develop,结果以下图三所示。 
 
图三fetch

能够看见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后的状态。 
 
图四3d

 
图五blog

简单来讲,git rebase提取操做有点像git cherry-pick同样,执行rebase后依次将当前的提交cherry-pick到目标分支上,而后将在原始分支上的已提取的commit删除。
merge OR rebase
那何时用merge,何时用rebase呢? 
再举个例子: 
初始状态以下图六所示: 
和以前同样的是,develop分支也是在 (3.added merge.txt file)处从master分支拉取develop分支。不同的是两个分支各个commit的时间不一样,以前develop分支的4和5commit在master分支3以后6以前,如今是develop分支的4提交早于master分支的5提交,develop分支的6提交晚于master的5提交早于master的7提交。 
 
图六it

在上图状况下,在master分支的7commit处,执行git merge develop,结果以下图七所示: 
 
图七ast

执行git rebase develop,结果以下图八所示: test


 
图八可视化

1. 能够看出merge结果可以体现出时间线,可是rebase会打乱时间线。 
2. 而rebase看起来简洁,可是merge看起来不太简洁。 
3. 最终结果是都把代码合起来了,因此具体怎么使用这两个命令看项目须要。
还有一点说明的是,在项目中常常使用git pull来拉取代码,git pull至关因而git fetch + git merge,若是此时运行git pull -r,也就是git pull –rebase,至关于git fetch + git rebase原理

最后推荐一些git可视化工具,我用的是gitkraken,这些工具功能基本同样,看我的喜欢好使用

鸣谢:感谢个人同事张帆同窗在git方面的指导  

相关文章
相关标签/搜索