首页投稿(暂停使用,暂停投稿)程序员Git使用

聊一聊git中merge和rebase

2016-12-18  本文已影响173人  mdiep

聊一聊git中merge和rebase

昨日,看到以前的老大在朋友圈中发了一条moment

"作为一个刚入职三天的新职员,如何劝说上级使用rebase,rebase,rebase,不要使用merge,merge,merge"

以前跟着这位老大,每次都是看他使用rebase,现在自己进行项目管理了,平时基本使用的都是merge,刚好今天回忆起来,就来看看什么是rebase,和merge。

首先可以肯定的是,merge和rebase都可以达到一种效果,就是分支的合并

merge

merge很容易理解,就是合并。在项目管理中,假设开始都在一条分支master上开发,到某一个时间点,项目发布出去了。然后新的需求issue来了,我们在当前master新开启一个分支iss53进行开发,如下命令行和图片。

git branch iss53     // 新建分支iss53
git checkout iss53 // 切换分支到iss53

git checkout -b iss53 // 上两个语句的简写
git_merge_rebase01.png

随着工作的进展,iss53每次提交,iss53指针就会不断往后延伸。如下

git_merge_rebase02.png

此时,iss53工作已经结束了,可以发布了,需要将iss53的代码合入到主分支master中。

git checkout master // 切换回主分支
git merge iss53 // 合并分支iss53

如果是这种情况,由于master和iss53有同一个父节点,所以只需要将指针master移到iss53处就可以,这种情况称之为Fast Forward

另一种情况,当iss53开发到中途的时候,线上版本出现了一个bug,现在需要切回到主分支master修复,为了不影响master,我们在主分支上新开一个分支hotfix。并在该分支上修改。

git checkout master     // 切回主分支
git checkout -b hotfix  // 在主分支上新开启一个分支hotfix

经过一段时间的修改,并且提交新的节点C4,当前指针hotfix指向的也是C4。经过测试C4节点已经成功修改了Bug,所以需要将hotfix合并到主分支master。

git_merge_rebase03.png

对应的命令行指令是

git checkout master // 切换回主分支
git merge hotfix        // 合并分支hotfix

由于master和hotfix有着同样的祖先节点C2,所以合并hotfix分支属于Fast Forward

git_merge_rebase04.png

此时就可以删除hotfix分支了

git branch -d hotfix // 删除分支hotfix

假设此时iss53也开发完成了,并且测试通过了。现在就需要将iss53分支上的东西合并到master分支上了。如上图,此时当前指针master并不在iss53的祖先节点上。但是我们同样可以通过如下命令进行合并

git checkout master // 切换回主分支
git merge iss53     // 合并分支iss53

此处就不是属于Fast Forward,git会主动的去寻找分支master和iss53共同祖先节点C2,然后去判断之后两个分支的修改,进行合并,最后会产生一个新的快照节点C6,而C6节点是包含了master和iss53所以修改的节点

git_merge_rebase05.png

此时就可以删除iss53分支了

git branch -d iss53     // 删除分支iss53

以上,基本上就是merge的基本介绍了

更详细的可以参照:分支的新建与合并

rebase

从字面意思上来说,可以译为重新构建(重演,衍合)。

首先我们先从下图开始,表示两个分支experiment和master都进行了开发。此处当然可以通过merge来合并experiment(上文已经介绍)。此处我们来解释如何用rebase(衍合)来进行代码的合并,它们两者间的工作原理是不一致的。

git_merge_rebase06.png

进行衍合操作(衍合分支experiment)

git checkout experiment // 切换到分支experiment(merge操作都是先回到主分支)
git rebase master   // 在分支master上重演experiment的提交历史

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

git_merge_rebase07.png

最后回到主分支,进行一次快速合并(Fast Forward)即可

git checkout master // 切回道主分支
git merge experiment // 快速合并
git_merge_rebase08.png

此处的快照节点C3'其时和直接合并产生的快照节点是内容是一致的。但是在提交历史过程中,就感觉是只在一个分支上开发,使的分支都是线性的。这里也将合并分支代码的conflict风险分担到了当前rebase的开发者身上。

另一种理解可以是这样,rebase相当于撤销了当前分支的所有提交,并找到主分支上最后一次提交节点,再之后经过计算,给主分支进行打补丁,最后产生C3'节点。

以上仅仅是最基本的衍合操作,当有多分支的时候,可以参照以下详细页(感觉太长了。。)

更精彩的详情

参照:rebase-分支-分支的衍合

最后,还是提示,光看还是不够的,操作才是硬道理,基于github,边看边玩,想怎么玩都行。


喜欢请随意


聊一聊git中merge和rebase
上一篇下一篇

猜你喜欢

热点阅读