聊聊merge和rebase

 

整理文,求看官给一点晚饭钱...



合并代码的两大工具

把一个分支中的修改整合到另一个分支的办法有两种:merge 和 rebase。

merge

merge是比较常见的使用方法,它会把两个分支最新的快照以及二者最新的共同祖先进行三方合并,合并的结果是产生一个新的提交对象。这种合并分支的好处是带有时间线,显示说明各个分支的前后关系。操作命令:

git checkout feature

git merge master

或者合并为一句: git merge master feature

feature分支中新的合并提交(merge commit)将两个分支的历史连在了一起。你会得到下面这样的分支结构:



merge的缺点也很明显,每次合并上游更改时feature分支都会引入一个外来的合并提交。如果master非常活跃的话,这或多或少会污染你的分支历史。我们在参与一个比较大的项目开发时,就会增加理解项目历史的难度。如下图,你很难找的清各个分支的关系了。



rebase

rebase操作翻译为衍合,我语文不太好,不是非常理解这个含义。rebase的价值在于你可以把当前分支中提交的改变移到另一个分支里重放一遍。为原分支上每一个提交创建一个新的提交,重写了项目历史,并且不会带来合并提交。操作命令:

git checkout feature

git rebase master

rebase的原理是回到两个分支最近的共同祖先,根据当前分支(也就是要进行衍合的分支 experiment)后续的历次提交对象,生成一系列文件补丁,然后以基底分支(也就是主干分支 master)最后一个提交对象为新的出发点,逐个应用之前准备好的补丁文件,最后会生成一个新的合并提交对象,从而改写 experiment 的提交历史,使它成为 master 分支的直接下游。视图如下:



rebase最大的好处是你的项目历史会非常整洁。它不像git merge 那样引入不必要的合并提交,导致看起来眼花缭乱。相反,rebase会让目历史呈现出完美的线性——你可以从项目终点到起点浏览而不需要任何的Fork。这让你更容易使用git log 、git bisect 和gitk 来查看项目历史。

不过,这种简单的提交历史会带来两个后果:安全性和可跟踪性。如果你违反了Rebase黄金法则,重写项目历史可能会给你的协作工作流带来灾难性的影响。此外,rebase不会有合并提交中附带的信息,所以你看不到feature分支中并入了上游的哪些更改。这可能不方便确认之前代码变更的背景和原因。

Rebase的黄金法则

一句话:绝不要在公共的分支上使用它。

比如说,如果你把master分支rebase到你的feature分支上会发生什么:



这次rebase将master分支上的所有提交都移到了feature分支后面。问题是它只发生在你的代码仓库中,其他所有的开发者还在原来的master上工作。因为rebase引起了新的提交,Git会认为你的master分支和其他人的master已经分叉了。

同步两个master分支的唯一办法是把它们merge到一起,导致一个额外的合并提交和两堆包含同样更改的提交。不用说,这会让人非常困惑。

总结:如果把rebase当成一种在推送之前清理提交历史的手段,而且仅仅rebase那些尚未公开的提交对象,就没问题。如果rebase那些已经公开的提交对象,并且已经有人基于这些提交对象开展了后续开发工作的话,就会出现叫人沮丧的麻烦。多人协作的项目,估计还是要继续老老实实的merge代码。


    关注 一点半克


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册