Git合并分支实践

Git分支合并是我们绕不过的坑,尤其是在多Topic分支同步开发中。作为Git仓库的Owner怎么样,更安全,更高效的完成Git分支的合并工作。

准备工作

我预先在GitHub上创建一个仓库GitBranchPractice

分支说明:

  • master:主分支,外发release分支;
  • dev_share:开发分享功能的Topic分支;
  • dev_im:开发即时聊天功能的Topic分支;
  • dev_share_bak:作为dev_share分支的备份,以便演示;
  • dev_im_bak:作为dev_im分支的备份,以便演示;

大家主要关注master,dev_im和dev_share分支,先看看分支关系图。
分支关系图

dev_im分支提交记录如下:
dev_im分支提交记录

dev_share分支提交记录如下:
dev_share分支提交记录

在dev_im和dev_share的修改记录中,同时修改common.txt文件,以创造合并冲突。

合并的目标是把分支dev_im的提交记录合并到分支dev_share上

好的,现在准备开始合并dev_im和dev_share分支。

尝试合并

Git支持merge和rebase两种方式合并代码,两个方式各有利弊。今天我们的合并功能使用rebase方式完成,如果对rebase了解不是很深入,请详细阅读下参考文章中的文章。

第一步:rebase

切换到分支dev_share下,执行git rebase dev_im命名。
git rebase dev_im
和我们预想的一样,在rebase过程中发生了冲突。

第二步:解决合并冲突

rebase合并过程中,先后会产生两次冲突,具体冲突入下图:
冲突细节1
冲突细节2

以上两个冲突解决起来比较简单,最终合并好的common.txt内容如下:
合并结果

本地分支dev_im合并到本地分支dev_share后,dev_share的提交记录如下图:
合并后dev_share提交记录
在此图中,完美的解释了rebase的工作原理。找到dev_im与dev_share的Parent节点,把dev_share的每个提交在dev_im上重衍。大家要注意dev_share的提交记录,在rebase前后的commit id 是不一致的

这里推荐一个一个Git命令

1
git merge-base commit1 commit2

使用此命令可以找到commit1与commit2的Parent节点。

第三步:远端分支同步

完成本地分支合并后,本地分支与远端分支的情况如下:
分支现状

本地分支dev_share提交记录如下:
git pull --rebase
本地分支dev_share状态如下:
当前状态
当完成本地分支dev_im合并到本地分支dev_share后,发现与远端分支dev_share产生分歧,提示git pull完成同步。
使用git pull -rebase与远端分支完成同步。

看到这个冲突,已经内牛满面,这个冲突命名之前已经解决过,现在为什么有出现啦?一个冲突解决两次这个不是我们所期望的。

大家已经注意到rebase后,本地分支dev_share之前的提交记录commit id已经发生了变化。本地分支dev_share和origin/dev_share 的Parent节点为分支master的最后一次提交,所以在git pull -rebase时,会把dev_share的六个提交记录在origin/dev_share上重衍,所以会再次出现冲突。

最佳实践

尝试合并中第三步远端分支同步后,会发生再次重衍。如果在合并dev_im和dev_merge时,发生冲突(有些冲突,开发中无法避免),那么如果绕过再次重衍的过程,就可以避免两次解决冲突的尴尬。

第一步:创建本地Merge分支

找到本地分支dev_im和dev_share的Parent节点,创建本地分支dev_merge,dev_merge的作用是dev_share的替代者
在演示实例中,Parent节点恰好是master分支,当然我们可以通过git merge-base dev_im dev_share找到Parent节点。

确定Parent节点,创建dev_merge分支
确定Parent节点为cbe416b36a6351c457b0e6bd5f965b037dd2780c,通过Parent节点创建本地分支dev_merge。
确认dev_merge分支
确认dev_merge的最后一个commit id为cbe416b36a6351c457b0e6bd5f965b037dd2780c

第二步:合并分支

目标是把dev_im与dev_share的提交合并到dev_merge中。
git rebase dev_sharegit rebase dev_im后,dev_merge的提交记录如下:
dev_merge的提交记录
在dev_merge分支上,可以看到从dev_im上合并的commit id未发生变化,从dev_share上合并的commit id同尝试合并一样,发生了变化。

第三步:同步到远端

第一步:创建本地Merge分支中,已经提前指出dev_merge的作用是dev_share的替代者。在完成本地合并后,我们需要及时的同步到远端,以便其他小伙伴继续coding起来。

1
git push origin dev_share

把本地的dev_merge推送到origin/dev_share分支,其他小伙伴只需在dev_share分支上git pull --rebase便可以继续开发工作。

总结

在这里再次提醒下,我们合并的目标是把分支dev_im的提交记录合并到分支dev_share上。完成合并后,需要保证:

  • dev_im的后续提交可以轻松的再次合并到dev_share中;
  • dev_share的远端库可以轻松同步到其他小伙伴。

注意

按照最佳实践的方式,需要Owner与小伙伴及时沟通,保证小伙伴们在合并过程中不要把本地dev_share的的提交同步到远端,以避免在第三步:同步到远端时,丢失小伙伴的提交记录。

参考文章