git merge时merge/squash merge/rebase merge的区别

merge

1. merge

$ git checkout master
$ git merge dev

这是最基本的 merge,会把分支的提交历史原封不动地拷贝过来,如果 master 此后已经有了新的提交,那么本次 merge 时还会额外自动创建一条 commit 信息用于记录本次 merge 操作。

2. squash merge

$ git checkout master
$ git merge --squash dev

字面意思,相比 merge 来说会减少分支合并的记录,会被压缩为一条 commit 记录。squash merge 本质是把 dev 分支的改动放到暂存区,接下来还需要手动提交一下,因此最终提交者变成了操作 master 分支的人,这可能是个弊端。

3. rebase merge

$ git checkout dev
$ git rebase -i master
$ git checkout master
$ git merge dev

rebase merge 可以完美解决 squash merge 可能会变更原始提交者的问题。

首先 rebase 这个概念如果不懂可以先去了解下,这里先进行 rebase 的意义,个人认为,一方面是为了和 master 分支同步一下信息,以免 master 在和 dev 分叉之后又有了额外的更新;另一方面,能真正解决 squash merge 痛点的是 -i 交互模式,会进入文本编辑框,由自己指定 dev 相对于 master 新产生的这些“补丁” 在 rebase 时具体该如何应用到当前 dev 分支上。

所以 rebase merge 是非常灵活的,你可以什么都不干,采用默认策略:

pick xxxxxxx A
pick xxxxxxx B
pick xxxxxxx C

也可以把所有 commit 合为一条,保存退出后,会再次进入一个用于编辑合并后提交信息的文本编辑框:

pick xxxxxxx A
squash xxxxxxx B
squash xxxxxxx C

还可以不合为一条,而只合并其中某几条,比如把 A,B,C 三条提交记录整合为 AB,C 两条记录:

pick xxxxxxx A
fixup xxxxxxx B
pick xxxxxxx C

文本编辑框中定义的指令合理的话,应该会顺利 rebase 成功,之后可以 git log 查看一下是否如愿。
最后,在 master 分支上进行 git merge dev 就是常规操作了。

所以 squash merge 和 rebase merge 在多条合并为一条时的区别是,前者在 merge 时才合并为一条,而后者在提前 rebase 时就顺便整合了多条 commit 信息。

4. 更灵活的 rebase

和刚才 rebase 的区别在于自己定义处理哪些提交记录。
我就是觉得当前分支前面几次提交记录有些啰嗦,我不是要整合从母分支(比如master)分叉以来的所有记录,而只是想整合最近的两次记录:

$ git log

* bfdbf07 - (HEAD -> dev) fix(global): 修复侧面栏固定式不可滚动 (31 seconds ago) 
* b549672 - (origin/dev) fix(产品管理): 尝试修复分页bug (4 hours ago) 
* 0486276 - fix(global): 统一【返回上一页】link样式和位置 (24 hours ago) 
$ git rebase -i HEAD~2

pick b549672 fix(产品管理): 尝试修复分页bug
squash bfdbf07 fix(global): 修复侧面栏固定式不可滚动

意思是把第二条和第一条合并,保存退出后,会再次进入编辑状态,用于提供文案,再次打字并保存退出后,查看提交记录:

$ git log

* 0976cd2 - (HEAD -> dev) fix: 修复产品管理分页bug;修复侧面栏固定时不可滚动bug (3 minutes ago) 
* 0486276 - fix(global): 统一【返回上一页】link样式和位置 (24 hours ago) 

参考:

  1. git merge的三种操作merge, squash merge, 和rebase merge

你可能感兴趣的:(git merge时merge/squash merge/rebase merge的区别)