首先,根据我的经验,如果你的场景是团队(多人)同时开发分支。那么Rebase 就不适合了。因为如果您的一位同事执行rebase,它可以修改所有提交。同时,如果另一个人在开发这个分支,很可能找不到公共父节点,无法提交commit。
rebase 可以让历史更清晰(一行),但merge 不行。
变基 vs 拉取请求 vs 合并
拉取请求只是用来提出一个请求来决定如何“解决”分支之间的提交。提出拉取请求后,您可以决定选择哪种合并类型的策略。
为了更好的解释Rebase和Merge,这里我先设置场景:
假设您有两个分支,master 和 develop。 develop 是从 master 在 (3. added merge.txt 文件) 提交的分支:
现在,设置 HEAD 位于 6.add hello.txt 文件,这是 master 分支的最新提交。
基于以上场景,执行git merge develop。下面是显示的结果:
Git 会按照两个分支的共同祖先自动进行三向合并(3.添加merge.txt文件) em>,(6.added hello.txt file) 和(5.added test.txt file) 两个分支的最新提交。然后根据merge中修改的内容生成一个新的commit,即commit 7。合并分支“开发”。
这就是merge的效果,简单的合并了两个分支,生成了一个新的提交。
另外,基于上述场景,执行git rebase develop。下面是显示的结果:
可以看到develop分支和fork都消失了。
在执行rebase操作时,git会从当前分支(master)中提取出changes(6.added hello.txt file),而这个变化是start从两个分支(3.added merge.txt file)的共同祖先开始的.
然后让master分支指向目标分支develop最新的commit(5.added test.txt file)。并将刚才提取的更改应用于此最新提交。
如果提取有多个更改,则 git 将依次应用于最新的提交。如下图,左边是初始状态,右边是rebase执行后的状态:
一句话,git rebase 提取操作有点像git cherry-pick(只是相似,但不一样)。 rebase 执行后,会依次cherry-pick当前提交,然后发送到目标分支。之后,原始分支上提取的提交被删除。
总结:
可以看到merge的结果可以反映时间线,但是rebase会打乱时间线。两者都可以实现代码组合,只针对公共分支,如master,不建议使用Rebase。
另外,merge 的麻烦在于回滚提交节点。但是因为 rebase 是在 rebase 完成之后,你将不知道你从哪里拉出了开发分支,这就是我所说的破坏历史时间线。