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

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

一、代码合并

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

1、git merge

下方就是我们要达到的目标,下方是我们达到下方目标所要做的事情:

  • 首先需要做的就是创建一个新的分支bugFix, 并切换到该分支上,然后进行一次C2的提交。

  • 然后再切回到master分支上,进行一次新的提交(C3)。

  • 最后要做的就是在master分支上执行一次合并操作,将bugFix分支上的提交合并到master分支上,C4就是合并后的节点。

  

下方对应的就是我们实现上述目标所对应的命令操作,具体如下所示:

  • 首先使用 git checkout -b bugFix, 新建并切换到bugFix分支上,并且使用 git commit 命令进行一次提交生成C2节点。

  • 然后使用 git checkout master 命令切换到master分支上,并且使用 git commit 命令进行一次提交生成C3节点。

  • 最后的话,就是在 master 分支上执行 git merge bugFix命令,将bugFix分支合并到master分支上,合并后会生成一个新的C4节点。具体如下所示:

  

 2、git rebase 

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

  • 首先需要做的就是创建一个新的分支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延续下来的新分支。

  

二、分离HEAD

1、移动HEAD指针

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

  

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

  

2、在提交树上移动分支

下方要完成的不单单是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指针进行上移。

  

3、撤销操作

接下来我们来看一下撤销操作,同样左边是我们要完成的目标,右边是初始状态。从下方的目标中我们可以看出 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操作一样。具体如下所示:

  

三、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分支上了。具体如下所示:

  

2、交互式rebase

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

  

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

  

3、交互式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"

  

4、交互式rebase的squash操作

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

  

我们对该操作执行squash命令,如下所示,编辑完进行保存即可。

  

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

  

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

  

5、交互式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相关的内容。

Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase的更多相关文章

  1. Git知识总览(四) git分支管理之rebase 以及 cherry-pick相关操作

    上篇博客聊了<Git知识总览(三) 分支的创建.删除.切换.合并以及冲突解决>,本篇博客我们主要来看一下 rebase 变基相关的操作.rebase 操作和 merge 操作最终都可以达到 ...

  2. Git知识总览(二) git常用命令概览

    上篇博客我们从 git clone 和 git status 两个命令开始,引出了一系列的git操作命令, 请参见:<Git知识总览(一) 从 git clone 和 git status 谈起 ...

  3. Git知识总览(六) Git分支中的远程操作实践

    前几篇博客陆陆续续的讲了好多关于Git操作的内容,本篇博客仍然也不例外,不过本篇博客的主题是关于git的远程操作的.依照之前博客的风格,我们依然依托于LearningGitBranch中的相关内容来探 ...

  4. Git知识总览(三) 分支的创建、删除、切换、合并以及冲突解决

    前两篇博客集中的聊了git的一些常用命令,具体请参见<Git知识总览(一) 从 git clone 和 git status 谈起>.<Git知识总览(二) git常用命令概览> ...

  5. Git知识总览(一) 从 git clone 和 git status 谈起

    本篇博客是整理git相关知识的第一篇,因为之前一直是用SourceTree对Git的命令行操作用的不是特别熟,于是乎过了一遍ProGit(链接:https://git-scm.com/book/zh/ ...

  6. git知识总结-2.git基本操作之原理说明

    0.前言 本文主要对git常用命令的工作原理做一个详细的说明,常用命令主要包括: 1.git add git add相关命令很简单,主要实现将工作区修改的内容提交到暂存区,交由git管理. 2. gi ...

  7. git知识总结-2.git基本操作之操作汇总

    0.前言 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60-100个命令. 上图分别为: Workspace:工作区 Index / Stage:暂存区 Reposito ...

  8. git之rebase、merge和cherry pick的区别(面试常问)

    git flow图例镇楼 merge 这个简单,初学者常用.比如主分支是Dev,最新版本是01.然后小明基于此,搞了个feature 分支A,业务:打酱油.然后在上面多次提交,完成功能迭代开发,如A1 ...

  9. git知识总结-1.git基础之数据存储

    1.前言 git包含四种对象文件: blob tree commit tag(目前没用到,暂时忽略) 2. git对象的关系   图 git三种对象关系   粗略一看,可以大致感觉出blob类似于文件 ...

随机推荐

  1. UVa 11461 - Square Numbers【数学,暴力】

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  2. CodeForces776-A.Serial Killer-string

    A Serial Killer time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  3. UnityShader 表面着色器简单例程集合

    0.前言 这些简单的shader程序都是写于2015年的暑假.当时实验室空调坏了,30多个人在实验室中挥汗如雨,闷热中学习shader的日子还历历在目.这些文章闲置在我个人博客中,一年将过,师弟也到了 ...

  4. UEP-级联下拉

    级联查询在UEP中采用动态下拉的形式,cascadeid为关键字,注意jsp页面的id的相互嵌套关系, 数据库字段的数值的设置,和动态下拉SQL语句的书写. <td align="ce ...

  5. IE8兼容border-radius.

    我们知道,CSS3新增的很多简洁优美的属性,比如border-radius.box-shadow.border-image.gradients.RGBA...因为这些属性的出现,我们可以很方便的就写会 ...

  6. HDU 1242 Rescue(优先队列)

    题目来源: http://acm.hdu.edu.cn/showproblem.php?pid=1242 题目描述: Problem Description   Angel was caught by ...

  7. 算法,java代码实现打印万年历

      万年历 以1900年1月1号星期一为时间原点 星期日 第一天 星期一 第二天 星期二 第三天 星期三 第四天 星期四 第五天 星期五 第六天 星期六 第七天            1.计算出当前日 ...

  8. 启动tomcat时,一直卡在Deploying web application directory这块的解决方案

    本来今天正常往服务器上扔一个tomcat 部署一个项目的, 最后再启动tomcat 的时候 发现项目一直都访问不了,看了一下日志: [root@iz8vbdzx7y7owm488t4d89z bin] ...

  9. PHP条件语句if的使用

    方法/步骤 if(条件){是否执行的代码...}:这样的用法常用于判断单一条件,当然,可以可以用逻辑符号将多个条件组合成同一条件. if else语句:如果条件不成立,就会执行else后面{}里的代码 ...

  10. C#进行CAD二次开发环境配置

    最近被公司分配到了做CAD二次开发.也是初次接触这方面的东西,其实是有些无从下手的感觉.因为公司这边也没有人有时间带我,只能是自己看书,然后再写一些Demo,再结合实际的应用来一点点的学习.废话不多说 ...