在 Git
代码合并中 rebase
与 merge
都是十分常用的方式,本文将通过具体场景讲解二者有哪些区别。
一、Rebase
1. 需求场景
假设存在下述开发场景:
- 在
master
分支开发提交work-1
; - 接收到新需求,从
master
切分支到dev
并提交work-2
; - 原功能变更,回到
master
提交work-1.1
; - 回到
dev
继续开发;
经过上述的步骤操作之后,工程的 git
提交日志如下,分支 dev
为另一条分叉。
2. 分支合并
在上述的流程中可以看到,master
分支的与 dev
发生了内容异步。因此若继续在 dev
上进行开发需要先将 master
内容同步到 dev 分支。
先以 rebase
方式为例,继续上面的场景,在切换至 dev
后按下图选择:
此时若两个分支修改了同一内容将会提示冲突需要进行手动处理,完成后选择 Apply
。
再次查看 git
记录可以看到刚才分叉的分支现在已经合并为一条线性的流程。
这时候同样的我们需要 dev
分支的内容合并回 master
,且由于刚才已经解决完冲突问题,这时候就可以选择切换到 master
分支选择将 dev
分支 merge
过来。
完成后 master
和 dev
此时都实现了内容的同步,这便是一个相对将为完善的协同流程。
二、Merge
1. 分支合并
Rebase
与 Merge
二者都能实现分支的合并,那二者的区别在哪呢?
还是以上述的场景为例,按照同样的步骤得到下述结果。
回到 dev
分支,但这时候我们不选择 rebase
,而是按下图选择将 master
合并到 dev
:
完成后查看 git
提交日志可以看到与 rebase
不同的是其保留了图中紫色的分支提交记录,生成了一个新的节点拼接于两个分支之后。
2. 差异分析
那么这又有什么弊端呢?显然易见,当多人协议时重复上述步骤,那 git
提交记录就会像怀孕一样向右突出多条分支记录。
这里仅以三个需求分支为例,执行刚才的提交步骤得到下图结果:
分别将 master
分支 merge
到对应的需求分支,再次查看 git
记录可以看到此时的分叉已经就不是很美观了。
那如果选择的是通过 rebase
执行上步操作呢?可以看到此时的 git
记录明显更为简洁。
因此在实际开发中,通过首次选择 rebase
将公共分支合并到本地分支解决冲突,完成后通过 merge
再将本地分支合并到公共分支,由于此时冲突已经解决完毕因此可以直接进行合并,同时 git
日志也更为简洁。
3. 提交合并
在 git
中另涉及的一个较为实用的即 Squash
,在一个需求分支开发中,通常会涉及到多次提交例如下图:
但在发起合并请求时这些提交同属于一个需求,我希望将其合并为单个 commit
再发起合并请求,此时即可选择 Squash
。
在 IDEA 的 git 记录中选择需要本地分支中需要合并的 commit
,并选择 Squash commit
。
此时会提示你为合并后的 commit
重新设置提交信息。
完成后即可看到刚才的三个提交记录此时已经合并为单个,这时候再发起合并请求则只会有单个的 commit
记录。
三、总结归纳
1. Merge
在 merge
合并中,会先找到两个分支的首个岔路点(黄色),再找到两个分支的最新节点(红色),将这个两个节点合并生成一个新提交(率色),同时保留原有的分支结构。
2. Rebase
在 rebase
中,当合并时同样是先找到首个岔路点,但之后不同与 merge
的为其是执行拼接动作。
以刚才的示例而言,在 dev
中选择 rebase master onto dev
,即将当前 dev
分支内容拼接到 master
的最新提交之后。