Git知识总览(四) git分支管理之rebase 以及 cherry-pick相关操作
上篇博客聊了《Git知识总览(三) 分支的创建、删除、切换、合并以及冲突解决》,本篇博客我们主要来看一下 rebase 变基相关的操作。rebase 操作和 merge 操作最终都可以达到合并代码的效果,不过其对分支的影响不同。上篇博客中我们聊到了 merge操作。简单的说merge操作就是将两个commit进行合并,然后在这两个分支合并的基础上创建一个新的commit。而变基操作简单的说是改变提交的父类,在改变父类时进行合并操作。合并就可能产生冲突,所以rebase时也会产生冲突,下方会介绍到。
聊完rebase,下方还聊如何进行cherry-pick。cherry-pick的本质其实也是合并,只不过是可以将任意分支,任意提交合并到相关分支。当然只要是合并操作,都有可能产生冲突,下方会给出cherry-pick操作的基本使用以及如何解决cherry-pick时产生的冲突。
一、merge 与 rebase 的简单对比
下方是我们做操作之前的分支状态,共有 bugFix、side 、another 三个分支。现在我们要做的是分别使用 merge 和 rebase 将分支 side 中的内容合并到master分支。
首先我们先来看一下 merge 操作。上篇博客中已经详细的聊了merge的相关操作,再次就不做过多的展示了,下方只做了简单的展示。
-
首先切换到master分支
-
然后在master分支上执行 git merge side 操作,将side分支上的内容合并到master分支上。
-
最后如果需要的话,在将side分支的指针指向master分支即可。
然后我们再看一下 rebase 下的相关操作。
-
首先切换到 side 分支。
-
然后在 side 分支上执行 git rebase master 操作,将其变基到master分支上。
二、rebase的基本操作
首先我们来看一下在git分支管理中如何使用rebase, 以及rebase的后会起什么作用。下方会根据一系列的示例来看一下rebase操作的实际效果。首先我们先来看一下做rebase操作之前的分支状态,如下所示。目前除了master主分支外,还有其他三个分支,分别为bugfix01、bugfix02、bugfix03。
现在要做的事情是在 bugfix01 的分支上执行rebase操作,将其变基到master分支上。
下方是在 bugfix01分支上执行的 git rebase master 将bugfix01分支变基到master分支上,下方是变基后的分支状态。从下方的分支中不难看出,之前在 master 分支后方的 bugfix01现在跑到了master分支的后方,并且 bigfix01 分支上的两个提交(3cc582b、f47d2ac)不见了。取而代之的是基于master分支的两个新的提交(d6d82d8、14bc685)。这两个新的提交不但包含了3cc582b、f47d2ac这两个旧的提交的内容,而且还包含了master分支当前指向的分支(b79aa11)提交上的内容。
上面的表达也许有点抽象,下面我们可以话一张图来表示上述的关系。根据上面的分支关系,简单的画了一下上面的 rebase 操作所对应的关系图。rebase 操作完后,下方画红框的分支就被废弃掉了。然后bugfix01会指向rebase后的commit上。
接着上面的操作,可以切换到master分支,然后执行 git merge bugfix01 命令,将master分支快速移动到bugfix01分支上所指向的内容上。下方就是快速移动后的结果。经过这步后,就完成了一次rebase操作。从rebase操作的结果来看,其对 git 的分支进行了整理,换句话说,rebase操作可以将其他分支上的内容合并到主分支上,合并后之前的分支的指针的指向也会随之变化,变化后之前的提交就会被抛弃掉。
变基是存在一定风险的,在 ProGit上有一句话:Do not rebase commits that exist outside your repository. 大概意思就是说:不要在你的仓库在其他地方存在副本的情况下,对分支执行变基。也就是说,你从远程Clone下来代码,然后对之前的操作进行了rebase, 并且强推到远端。如果别人也clone的相关仓库,在其分支上做了相关操作。在push之前执行pull时,因为之前的分支被你rebase了,也就是有了新的提交,在pull时,就会进行merge操作。这样一来,分支就会更加复杂。如果出现上述问题 就使用rebase 来解决问题,即使用 git pull --rebase 来执行。
这一块具体的东西还是参考ProGit上的内容来的比较直观,在此就不做过多赘述了。
三、rebase的冲突解决
为了看rebase冲突的解决方式,我们故意的制造了下方的冲突,然后去执行rebase操作。从下方的操作中不难看出,在rebase的过程中产生了冲突,需要我们去解决。解决冲突后将相关问题件进行commit, 然后使用 git rebase --continue 操作来继续rebase。
因为rebase时会合并多个提交,在多个提交合并时会产生多个冲突,所有在一个冲突解决并提交后,进行git rebase --continue继续合并接下来的点。继续后仍然有可能产生冲突,产生冲突即解决冲突,直到rebase结束为止。
四、cherry-pick的基本操作
接下来我们来看一下git中比较实用的一个命令:cherry-pick。这个命令的名字是比较形象的,cherry-pick即“摘樱桃”,使用该命令可以将任意的commit通过其commit号将其合并到你想要的分支上。接下来我们就来看一个例子。
下方就演示了cherry-pick命令的使用方法。在 master 分支上,执行 git cherry-pick <一些commit的哈希值> 然后将这些提交合并到master分支上。这些分支会根据cherry-pick的顺序进行merge,每次merge都会形成一个新的提交。与rebase命令不同,虽然会产生一个新的提交,而之前的提交是不变的。具体如下所示:
接下来我们来看一下具体在终端上cherry-pick的操作命令。下方是目前分支的状态,并且处于master分支上。现在我们要做的事情是将 d98ff43 这个commit 拿到master上。
下方就是我们执行cherry-pick的命令,如下所示。下方执行cherry-pick时是非常顺利的,没有产生冲突。当提交进行合并时会产生冲突,就不是这个样子了,稍后会演示到。
下方就是顺利的cherry-pick后的样子。
五、cherry-pick的冲突解决
在cherry-pick时遇到冲突是避免的,下方特地搞了一个cherry-pick冲突的例子。为了更进一步的了解冲突的解决方式,下方cherry-pick了多个提交,而且这多个提交在merge时都会有冲突。下方我们会对这些冲突进行解决。
-
首先我们在master分支上通过 git cherry-pick <一系列提交的哈希值>来将 4f8e019、dbe9e8a、5c52520这三个提交摘到master分支上。
-
然后我们会先看到在cherry-pick 4f8e019 这个提交时产生了冲突,报了一个Error:提升不能将cherry-pick命令应用于4f8e019。并且下方给了一系列的提示(解决此错误可以通过正确的方式解决冲突,然后通过git add 或者 git rm将更改的文件进行追踪,最后可以使用 git commit进行提交)
-
解决一个冲突并commit后,使用 git cherry-pick --continue可以进一步的进行下一个提交的cherry-pick。下方再次执行git cherry-pick --continue时,又出现了冲突,此刻我们还是按照上述的步骤对冲突进行解决,解决完毕后接着git cherry-pick --continue。直到所有的commit被合并完毕即可。具体操作步骤如下所示:
下方是上述操作的最终结果,cherry-pick了三个commit,冲突了三次,解决了三次。如下所示:
下篇博客会继续聊Git的相关的内容。
作者:青玉伏案
出处:http://www.cnblogs.com/ludashi/
本文版权归作者和共博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果文中有什么错误,欢迎指出。以免更多的人被误导。
收简历:坐标美团(北京总部),长期招聘FE/iOS/Android靠谱工程师,入职后,可内部联系楼主,有小礼品赠送,有意者可邮箱投递简历:zeluli@foxmail.com