上篇博客聊了《Git知识总览(三) 分支的建立、删除、切换、合并以及冲突解决》,本篇博客咱们主要来看一下 rebase 变基相关的操做。rebase 操做和 merge 操做最终均可以达到合并代码的效果,不过其对分支的影响不一样。上篇博客中咱们聊到了 merge操做。简单的说merge操做就是将两个commit进行合并,而后在这两个分支合并的基础上建立一个新的commit。而变基操做简单的说是改变提交的父类,在改变父类时进行合并操做。合并就可能产生冲突,因此rebase时也会产生冲突,下方会介绍到。html
聊完rebase,下方还聊如何进行cherry-pick。cherry-pick的本质其实也是合并,只不过是能够将任意分支,任意提交合并到相关分支。固然只要是合并操做,都有可能产生冲突,下方会给出cherry-pick操做的基本使用以及如何解决cherry-pick时产生的冲突。git
1、merge 与 rebase 的简单对比ide
下方是咱们作操做以前的分支状态,共有 bugFix、side 、another 三个分支。如今咱们要作的是分别使用 merge 和 rebase 将分支 side 中的内容合并到master分支。post
首先咱们先来看一下 merge 操做。上篇博客中已经详细的聊了merge的相关操做,再次就不作过多的展现了,下方只作了简单的展现。url
首先切换到master分支
而后在master分支上执行 git merge side 操做,将side分支上的内容合并到master分支上。
最后若是须要的话,在将side分支的指针指向master分支便可。
而后咱们再看一下 rebase 下的相关操做。spa
首先切换到 side 分支。
而后在 side 分支上执行 git rebase master 操做,将其变基到master分支上。
2、rebase的基本操做3d
首先咱们来看一下在git分支管理中如何使用rebase, 以及rebase的后会起什么做用。下方会根据一系列的示例来看一下rebase操做的实际效果。首先咱们先来看一下作rebase操做以前的分支状态,以下所示。目前除了master主分支外,还有其余三个分支,分别为bugfix0一、bugfix0二、bugfix03。指针
如今要作的事情是在 bugfix01 的分支上执行rebase操做,将其变基到master分支上。htm
下方是在 bugfix01分支上执行的 git rebase master 将bugfix01分支变基到master分支上,下方是变基后的分支状态。从下方的分支中不难看出,以前在 master 分支后方的 bugfix01如今跑到了master分支的后方,而且 bigfix01 分支上的两个提交(3cc582b、f47d2ac)不见了。取而代之的是基于master分支的两个新的提交(d6d82d八、14bc685)。这两个新的提交不但包含了3cc582b、f47d2ac这两个旧的提交的内容,并且还包含了master分支当前指向的分支(b79aa11)提交上的内容。blog
上面的表达也许有点抽象,下面咱们能够话一张图来表示上述的关系。根据上面的分支关系,简单的画了一下上面的 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上的内容来的比较直观,在此就不作过多赘述了。
3、rebase的冲突解决
为了看rebase冲突的解决方式,咱们故意的制造了下方的冲突,而后去执行rebase操做。从下方的操做中不难看出,在rebase的过程当中产生了冲突,须要咱们去解决。解决冲突后将相关问题件进行commit, 而后使用 git rebase --continue 操做来继续rebase。
由于rebase时会合并多个提交,在多个提交合并时会产生多个冲突,全部在一个冲突解决并提交后,进行git rebase --continue继续合并接下来的点。继续后仍然有可能产生冲突,产生冲突即解决冲突,直到rebase结束为止。
4、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后的样子。
5、cherry-pick的冲突解决
在cherry-pick时遇到冲突是避免的,下方特意搞了一个cherry-pick冲突的例子。为了更进一步的了解冲突的解决方式,下方cherry-pick了多个提交,并且这多个提交在merge时都会有冲突。下方咱们会对这些冲突进行解决。
首先咱们在master分支上经过 git cherry-pick <一系列提交的哈希值>来将 4f8e01九、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的相关的内容。