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操作时的具体案例。

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相关的内容。

原文地址:https://www.cnblogs.com/ludashi/p/8213550.html

时间: 2024-10-06 12:29:56

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

Git使用教程(五)--Git重写历史

1. git commit –amend 如果仅仅想修改刚刚的提交(最后一个提交),可以使用git commit --amend修改最后一次提交.使用该命令时会弹出对话框(windows下)或者vim编辑界面(linux下).在弹出界面进行修改,保存后即可用新的提交信息进行提交了.该命令只能修改提交备注信息,对于其他信息无法修改. 2. git reset –soft head^ 该命令会回滚最后一个提交,执行一次表示回滚最近一次提交.然后改动会进入暂存区,可以使用git commit -m继续

git知识总结-4.git服务器搭建及迁移git仓库

1. 前言 因为手里有一份代码之前是直接从其它git服务器上克隆下来的,现在想自己搭建一个git服务器把这份代码管起来. 2. 搭建git服务器 1.安装git: $ sudo apt-get install git 2. 创建一个git用户,用来运行git服务: $ sudo adduser book 3. 创建证书登录 收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/book/.ssh/authorized_keys文件里,一行一个. 此处可

Git中的merge命令实现和工作方式

想象一下有如下情形:代码库中存在两个分支,并且每个分支都进行了修改,最后你想要将其中的一个分支合并到其他的分支中.个人博客网址 http://swinghu.github.com/ 那么要问合并的处理过程是怎么样的呢?Git是对每个分支,依据分支的历史数据按照序列化操作,还是它只是合并每个分支里文件的最后版本?这是一个问题,我想对git的merge操作有必要进行分析一下. 回忆一下,我们知道Git的版本库内部结构是以有向无环图(directed acyclic graph)组织起来的:每一次co

使用Git中的Merge与Rebase与开源项目同步代码

基于开源项目的开发有两种主要工作模式.模式1是在从开源项目中拉出一个分支,在这个分支中开发新feature,完成后合并到upstream中.适用于本身是开源项目的developer.模式2是从开源项目中拉出分支后独立发展,但定期从upstream拉更新(如重要版本升级时).无论是哪种,都会面临本地分支与upstream同步代码的问题.为此,git主要提供了两种方式:一种是merge, 一种是rebase.下面通过例子简单过一下它们的基本流程. 假设开源项目的git地址为git://xxx.org

关于Git中分支merge和rebase的适用场景及区别

最近刚接触Git,下面对一些基本的使用做一下总结. 本文是转载于CSDN:http://blog.csdn.net/rryqsh/article/details/8230560 几乎所有的版本控制工具都有branch功能,branch主要用于以下几个场景: 1,控制产品OEM. 基本上做产品,不同的客户都会提出多种不同特性需求,最简单的例子就是LOGO和标题完全不一样.但是可能产品自身的大部分功能和模块的代码一样的,这个时候如何管理多个客户定制的功能特性,并且不会干扰其他OEM版本的功能呢? 如

git中的merge与rebase

之前一直对git的merge与rebase很困惑,而且一般也只使用merge而不是使用rebase.今天受高人指点理清了两者的区别. 首先对于两者而言,他们的结果是一样的,差异在于合并的方式(产生的结果就在于log中看起来会让人感觉到有问题,也就是两者的commit记录会有很大差异) merge的合并方式: 使用rebase的话: 补充点: pull/fetch的区别: fetch只是单纯的拉取代码. pull的实际操作:fetch-merge.所以当远程代码有更新时,本地pull后会可能需要处

git小技巧--如何从其他分支merge个别文件或文件夹

在实际工作中,一个大型的项目或版本迭代可能不是一次上线,可能会分好几次上线,这时候就会涉及创建多个分支,进行分别开发. 创建分支 功能分为2个分支,分别为A.B. A上面有个列表页功能 B上面有个详情页功能,还有个系统消息功能 产品经理说先上列表功能,于是我们就开发A分支,列表功能很快开发完成. 第二天按常理开发B分支,开发到一半,产品经理说目前的系统消息功能需要急着上线,要和列表功能一起上线,当时就懵逼了,然后赶紧放下详情页的开发,立马去开发系统消息功能,开发完之后需要将列表功能和系统消息功能

【android Studio】零git知识、零脚本命令,即刻体验git版本管理魅力!

git的优点就不去多说了.阻碍咱新手体验它的唯一问题就是门槛太高,脚本看着像天书, 本文主要阐述的,就是如何在android studio上,也能像tfs那样,非常简单的操作,就能使用git进行版本管理 几个月用下来,咱每天要做的就是开始工作前,alt+下方向键,从服务端拉取数据:结束工作后,alt+上方向键,将代码提交到服务器上.就这两步,完成了版本管理. 因此,有了这篇面向新手的图文并茂的文章,一步步按照步骤下来,你就可以完成项目对git的融合. (提示:面向新手的介绍型文章,因此步骤细致繁

git学习——<五>git分支

git学习——<一>git安装 git学习——<二>git配置文件 git学习——<三>git操作 git学习——<四>git版本管理 一.提出问题 今天开发的过程中遇到一个问题,A组接到开发任务要修改file文件,B组在此之前的15天为了完成自己的开发任务对file文件进行了修改,为了同步代码,B组将自己未完成的模块file文件提交到了cvs上.A对此一无所知,A组在完成开发任务后,把file文件完全上到了现网环境,报错了. 当然,避免上述问题的途径很多,