merge 合并分支

同一个分支也可能出现 merge 的情况,例如这边有一个老项目平时基本上没其他人动,所以在修改这个项目的时候基本上想不起来要先pull 一下,当然了,这是一个非常不好的习惯,所以有时候一push代码,发现有人竟然提交新代码上去了,所以这种情况下就自动 merge 一下。

这里主要讨论的是分支合并时的 merge。

下图是 merge 合并分支时前后版本变化的情况。

合并代码用 merge 还是用 rebase ? - 图1

merge 会创建一个新的合并提交,将两个分支的历史记录保留在一起。

它的特点就是日志保存完整,不管之前合并进来的那个版本有多少个提交历史,都会被完整的合并到目标分支。

以下是使用 merge 合并后的主分支 Graph 情况,看上去是不是有点乱。

合并代码用 merge 还是用 rebase ? - 图2

假设有两个分支,<font style="color:rgb(255, 93, 108);">main</font><font style="color:rgb(255, 93, 108);">dev</font>分支,在 dev 分支上开发,然后合并到 main 分支,合并的大致流程如下。

  1. git checkout main
  2. git pull origin main
  3. git merge dev
  4. # 解决冲突后
  5. git commit -m "Merge dev into main"
  6. git push origin main

Rebase 合并分支

<font style="color:rgb(255, 93, 108);">rebase</font> 会将分支上的更改重新应用在目标分支上,重写提交历史。

合并代码用 merge 还是用 rebase ? - 图3

rebase 方式提交的版本历史是线性的,不会创建新的合并提交,历史记录非常干净。

同样地,假设当前有两个分支,<font style="color:rgb(255, 93, 108);">main</font><font style="color:rgb(255, 93, 108);">dev</font>,用 rebase 方式合并分支的大致流程如下。

  1. git checkout dev
  2. git pull origin dev
  3. git rebase main
  4. # 解决冲突后
  5. git rebase --continue
  6. git push origin dev --force

合并压缩

在rebase 的时候还可以使用 squash 参数来压缩提交记录,例如下图,Feature 1 分支的 A、B、C 三个提交记录,使用 rebase squash 后会在主分支变为一个提交记录 F。

合并代码用 merge 还是用 rebase ? - 图4

使用方式如下,<font style="color:rgb(255, 93, 108);">git rebase -i HEAD~3</font> 命令准备压缩最近的3次提交,然后在编辑模式下将<font style="color:rgb(255, 93, 108);">pick</font> 改为 <font style="color:rgb(255, 93, 108);">squash</font>,最后推送到远端仓库。

适合那种

  1. git checkout dev
  2. git rebase -i HEAD~3
  3. # 进入编辑模式后,修改 `pick` 为 `squash`
  4. # 保存并关闭编辑器后,编辑新的提交信息并保存
  5. git push origin dev --force

选择使用哪种方法

具体使用哪种方式合并要根据场景和习惯而定,没有绝对的好坏。

使用 merge,如果希望保留分支的历史记录,并且不介意有合并提交。适用于团队合作时保留每个人的工作记录。

使用 rebase,如果希望保持提交历史的简洁和线性,适用于希望干净历史的项目。

有些公司规定只能用 rebase,它更适合那种只有单一版本的项目,只有一个主分支一直向前推进,且没有多个分支并行的情况,例如一个产品既要维护2.x 版本又要维护3.x版本,那用 rebase就不合适了。

之前 Vue 项目就是用 rebase 方式合并分支的。