Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase

上篇博客聊了《git分支管理之rebase 以及 cherry-pick相关操做》本篇博客咱们就以Learning Git中的关卡进行展开。下方列举了LearningGit中的 merge、rebase、reset、revert、cherry-pick 以及交互式rebase相关关卡的操做以及对应的解析。后边在聊交互式rebase操做是,不仅仅给出了LearningGit中的内容,并且给出了真正的Git分支在交互式rebase操做时的具体案例。html

learngitbranching的地址为:https://learngitbranching.js.org/git

 

1、代码合并shell

在下方示例中全部目标的初始化状态是下方这样的,而后咱们要按照目最终目标,使用相关的git命令来达到相关的目标。vim

 

 一、git merge编辑器

下方就是咱们要达到的目标,下方是咱们达到下方目标所要作的事情:ide

  • 首先须要作的就是建立一个新的分支bugFix, 并切换到该分支上,而后进行一次C2的提交。
  • 而后再切回到master分支上,进行一次新的提交(C3)。
  • 最后要作的就是在master分支上执行一次合并操做,将bugFix分支上的提交合并到master分支上,C4就是合并后的节点。

  

 

下方对应的就是咱们实现上述目标所对应的命令操做,具体以下所示:post

  • 首先使用 git checkout -b bugFix, 新建并切换到bugFix分支上,而且使用 git commit 命令进行一次提交生成C2节点。
  • 而后使用 git checkout master 命令切换到master分支上,而且使用 git commit 命令进行一次提交生成C3节点。
  • 最后的话,就是在 master 分支上执行 git merge bugFix命令,将bugFix分支合并到master分支上,合并后会生成一个新的C4节点。具体以下所示:

  

 

 二、git rebase spa

闯完git merge的关,咱们来看一下git rebase的关。下方就是咱们最终要实现的目标。实现下方目标和上面的merge操做差很少,只不过最后一步不是使用合并操做,而是在bugFix上执行变基操做,具体分析以下:3d

  • 首先须要作的就是建立一个新的分支bugFix, 并切换到该分支上,而后进行一次C2的提交。
  • 而后再切回到master分支上,进行一次新的提交(C3)。
  • 而后在切换到 bugFix 分支上,执行变基操做,将bugFix的父节点变成master分支,以前的C2节点就被新的提交C2`所替代了。

  

 

下方是咱们的具体命令操做:指针

  • 首先使用 git checkout -b bugFix, 新建并切换到bugFix分支上,而且使用 git commit 命令进行一次提交生成C2节点。
  • 而后使用 git checkout master 命令切换到master分支上,而且使用 git commit 命令进行一次提交生成C3节点。
  • 而后再使用 git checkout bugFix 命令切回到 bugFix 分支上。
  • 最后在bugFix分支上执行 git rebase master 命令,经其父类变成master。执行变基后,C2会和C3节点的内容进行合并生成新的节点C2`,而bugFix分支的指针也会从C2节点移动到C2`上,移动后bugFix以前的分支就会被废弃掉,取而代之的是从master延续下来的新分支。

   

 

2、分离HEAD

一、移动HEAD指针

HEAD指针是指向当前所在的操做分支,好比咱们如今是在master分支,那么HEAD就指向master分支,而后master分支指向的是咱们的commit号。分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。下方左边的图就是咱们要完成的目标,右边是咱们分支的初始化状态。

  

 

实现上述目标一行命令足矣,可使用 git checkout C3 命令就能够将HEAD命令指向C3提交上。git checkout HEAD^ 命令能够将HEAD指针向上移动一个距离,git checkout HEAD~3 则能够将HEAD向上移动三个距离。具体操做以下所示:

  

 

二、在提交树上移动分支

下方要完成的不仅仅是HEAD指针的移动,而是分支指针的移动,在Git上能够移动你所建立分支的指向,使其指向任意提交过的分支上。下方就来看一下如何在git上移动分支指针,下方左边是咱们要完成的目标,右边是分支的初始化状态。须要作的事情以下:

  • 将 bugFix 分支移动到C0上。
  • 而后将master分支移动到C6上。
  • 最后将HEAD分支上移。

  

 

须要操做的命令以下所示:

  • 首先使用 git branch -f bugFix C0 命令将bugFix指向C0节点。(C0表示的是相关提交的哈希值)。
  • 而后使用  git branch -f master C6 命令将master分支指向C6节点。
  • 最后使用 git checkout HEAD^ 命令将分离的HEAD指针进行上移。

  

 

三、撤销操做

接下来咱们来看一下撤销操做,一样左边是咱们要完成的目标,右边是初始状态。从下方的目标中咱们能够看出 local 分支的撤销操做是使用的 git reset 操做的, 由于是在本地来向上移动的,进行reset后是不能够push到远端的。而push分支使用的是revert操做,撤销了C2的提交后,再C2的基础上又生成了一个新的提交。reset 操做是不能够被push到远端的,而revert则能够,稍后会进行实验。下方会有具体的操做。

  

 

下方就是咱们为了完成目标而又的具体的操做:

  • 首先在 local 分支上执行 git reset HEAD^1 或者 git reset HEAD C1 操做来撤销本地的C3操做。
  • 而后咱们再经过 git checkout pushed操做切换到 pushed 分支上,而后执行 git revert HEAD^1 操做,撤销C2的提交。

  

 

若是你reset某个提交,想在将分支号移动到以前的提交上,可使用上面的 git branch -f 操做,将相应的分支移到相应的提交上。下方是将 local 分支又移动回了C3, 以下所示。

  

 

接下来我来看一下对 reset 后的分支进行push, 以及对 revert 分支后进行push。

  • 首先在local分支上执行reset操做,而后进行push会提示本地仓库和远程仓库产生了分歧,先git pull 或者 git pull --rebase
  • 而在pushed分支上的revert操做就不会有这样的提示,由于revert是在原来的分支下方产生了一个新的提交,和正常提交同样对待,因此是能够push的。

  

 

下方咱们再作个尝试,在一个分支上进行了reset , 而后在reset后的分支上作了一些提交。最后咱们将这些提交进行push,而后看一下具体的效果。

  • 首先咱们对clone到本地的local分支进行了reset操做,操做后在新的分支上进行两次commit。
  • 而后咱们进行push , 会提示先pull或者 pull --rebase , 而后在进行push.
  • 下方先执行了 git pull 操做,执行pull操做后,就是将 o/local 分支和 local分支进行合并,合并后就能够进行push了。这样一来,咱们以前reset操做就不起什么做用了。由于 pull 操做后进行了merge, 就等效于在C3上直接进行commit。
  • 而后咱们进行回退,又试了一下 git pull --rebase 操做,其实该操做就是将merge操做改为了变基操做。将咱们后来的C4, C5两个提交变基到C3上,从效果上看,就和没有执行reset操做同样。具体以下所示:

  

 

 

3、cherry-pick和交互式rebase

之因此将这两个放在一块,是由于使用二者均可以达到相同的目标,只是操做不一样。下方会分别介绍。

1. cherry-pick

下方咱们来看一下cherry-pick这一关,下方咱们须要将 bugFix 分支上的 C3 、side 分支上的 C4 以及another分支上的C7经过cherry-pick的形式拿到 master分支上。

  

 

下方主要仍是使用了cherry-pick来达到咱们的目标的,主要仍是一个命令的使用 , 在 master 分支上执行 git cherry-pick C3 C4 C7, 能够将C3 C4 C7这三个提交摘到master分支上了。具体以下所示:

  

 

二、交互式rebase

解析咱们来使用交互式rebase来作节点的迁移,固然下方的操做也是可使用cherry-pick来完成的。左边是咱们要完成的目标,右边则是初始化状态。咱们须要将C2 C3 C4 C5的提交顺序转换成C3, C5, C4的顺序。

   

 

下方就是咱们交互式rebase操做的具体步骤,本质上就一个命令 git rebase -i HEAD~4, 而后操做相关的节点便可。

  

 

三、交互式rebase实践

接下来咱们来看一下在真正的git分支上是如何使用交互式rebase操做的。下方是作交互式rebase操做以前的分支关系。目前所在的分支是bugFix, 其中有4个提交。

  

 

如今要作的是在bugFix上进行交互式rebase, 在终端中输入 git rebase -i master, 目的是将 bugFix 分支上的提交经过交互式rebase的方式将其变基到master分支上。下方是输入git rebase -i maste命令后所出现的界面,咱们能够经过vim编辑器编辑将要执行的变基操做。下方是对应的几种交互式命令

  • pick 应用相关提交。
  • reword 修改commit信息。
  • edit 对提交进行编辑,而后使用 git commit -amend进行提交。
  • squash 是把多个提交合并成一个提交
  • fixup 与squash差很少,不过会抛弃掉本次提交的log信息
  • exec 执行shell命令
  • drop 删除提交

  

 

 下方咱们对相关操做执行的交互式的操做:

  • 首先使用 reword 来操做下方截图中的第一条操做,用来修改message。
  • 而后交换了第二行和第三行的pick的位置
  • 而后对第四行的提交执行edit命令对其进行修改
  • 而后删除 编号为04的提交

  

 

点击回车键的话会弹出下方的vim编辑器来让你修改 f53560c 这个操做的commit message,修改完毕后进行保存便可。 

  

 

下方是在rebase合并时产生了冲突,咱们须要对冲突进行解决。解决完毕后,执行 git add 将冲突文件进行存储,而且执行git rebase --continue 来继续咱们的rebase操做。

   

 

通过一系列解决冲突的操做,最终咱们的rebase操做是成功的,会提示下方的 Successfully。

  

 

交互式rebase操做成功后,接下来咱们来看一下当前分支的状况,,从结果中咱们不难看出:

  • bugFix 分支上的提交已经变基到了master分支上。
  • “change aa.text 04”的提交已经被移除了。
  • “change aa.text 01” 和 “change aa.text 02” 的提交顺序进行了交换。
  • 而且 "create aa.text" 的log变成了 "create aa.text reword"

  

 

 

四、交互式rebase的squash操做

接下来咱们来看一下squash的操做,下方咱们会在当前所在分支和上次提交上执行squash操做,其对应的命令的为:git rebase -i HEAD~1,以下所示:

  

 

咱们对该操做执行squash命令,以下所示,编辑完进行保存便可。

  

 

保存后会出现下方的操做,目的是用来编辑两次提交合并后的commit message 的。

  

 

编辑完保存便可,下方就是咱们进行上述操做后所对应的相关信息。

  

 

五、交互式rebase的另外一个示例

接下来咱们来看一下另外一个交互式rebase的示例,完成下方的目标,咱们须要作下方几步:

  • 首先咱们经过交互式rebase将caption变基到master分支上,在变基操做时交换 C2 和 C3的位置。
  • 而后经过 git commit --amend 往 C2 上追加提交内容。
  • 最后再经过 git rebase -i 操做将C2和C3进行交换。

    

 

下方就是对应的具体命令操做:

  • 首先在caption分支上执行 git rebase -i master, 将caption分支经过交互式rebase的方式变基到master分支。
  • 在交互式变基时,修改了C2和C3的提交顺序。
  • 而后在经过git commit -amend 操做往C2上追加了一些修改。
  • 而后再经过git rebase -i master , 将C2和C3进行交换回来。
  • 最后将master使用git rebase 操做进行快速移动到caption上。

  

 

今天博客就先到这儿吧,下篇博客继续聊git相关的内容。

相关文章
相关标签/搜索