git rebase和merge使用简介

前言

git rebase 和git merge 作用基本是相同的,都可以用来合并两个branch。这里不对这两个命令做原理上的介绍,只是从实践的角度对这两个命令进行解释。如果不明白其中的原理可以自行查找。

准备

测试基本环境:本地创建一个git仓库,包括两个分支master和dev。两个分支保持同步都只有一次提交:

在这里插入图片描述
图1:初始化git仓库

然后分别在这两个分支上做两次提交,但是提交的时间顺序是穿插的。

branch master

在这里插入图片描述
图2:master log

branch dev
在这里插入图片描述
图3:dev log

按照时间先后 Master commit 1 -> Dev commit 1 -> Master commit 2 -> Dev commit 2

ID commit date
86894d7 Dev commit 2 18-10-19 14:06:11
ddf7f38 Master commit 2 18-10-19 14:05:31
912bf54 Dev commit 1 18-10-19 14:04:32
75944e4 Master commit 1 18-10-19 14:04:01

表1:按时间排序

使用merge合并

在master分支执行merge命令

$ git merge dev

看一下合并后的log信息:

在这里插入图片描述
图4:merge log

对比一下图4和表1可以发现:

  1. 执行merge后把dev分支的两次commit合并到master了,同时生成了一个Merge branch ‘dev’ 新的commit。这是用来标记合并信息。
  2. 根据log信息可以很明显的看到commit是按照时间先后进行排列的。
  3. 从dev合并到master的每一次提交的commit ID是没有变化的。

这三点也正是merge的特点,总的来说就是merge合并时创建一个新的commit进行标记并且保存了提交的原始记录

使用rebase合并

rebase使用起来比merge麻烦一些,在合并时要考虑到开发分支和基础分支。

以本文为例,我是以master为基础分支,以dev为开发分支(分支叫什么名字无所谓),所以我最终想要的结果是:基于master分支的提交把dev分支的提交添加上

在操作前先用git reset --hard命令把仓库的状态回退到执行merge之前,这样能保持commit ID与之前一样,方便对比。

执行命令:

$ git checkout dev
$ git rebase master

看一下合并后的log信息:
在这里插入图片描述
图5:rebase log

对比图5和图4和表1发现:

  1. 合并后并没有新的commit。
  2. 合并后的commit顺序不是按照时间的先后排序的。而是把dev分支的两个提交放到master分支的两个提交之上了。
  3. dev分支上的两个提交Dev commit 2Dev commit 1的commit ID已经和原始的不一样了。

这里介绍一下rebase的过程,git rebase master命令执行的时候会把dev分支(当前分支)里的每个提交取消掉,并且把它们临时保存为patch(这些补丁放到".git/rebase"目录中),然后把dev分支更新到到与master分支一致,最后把保存的这些patch再贴回来。

所以就造成了当前的现象:合并后commit信息并没有按照两个分支的提交顺序进行排序,而且会产生两个新的commit。

这就完了?

用回退版本的方式再验证一下merge和rebase的区别

rebase后回退(branch dev)

如图5所示,在branch dev上有五次提交,如果想要回退到Dev commit 1(commit ID:d6bfde7) 或者 Master commit 2(commit ID:75944e4) 会有怎么样的效果呢?

//回退到Dev commit 1
$ git reset --hard 912bf54

在这里插入图片描述
图6:Dev commit 1

//回退到Master commit 1
$ git reset --hard 75944e4

在这里插入图片描述
图7:Master commit 1

看上去是符合预期的,也是理所当然的,用reset --hare强制回退到某一个commit ID,必然能成功。
但是merge会是同样的表现吗?

merge后回退(branch master)

可以用reset --hard的方式把仓库强制更新到图4的状态。

在branch master上有六次提交,其中包括一次merge commit。强制撤销掉merge commit和回退到Dev commit 2(commit ID:86894d7)

//把merge commit撤销掉。
$ git reset --hard HEAD^

结果如下:
在这里插入图片描述
图8:reset --hard HEAD^

//回退到Dev commit 2。
$ git reset --hard 86894d7

结果如下:
在这里插入图片描述
图9:Dev commit 2

现在可以很明显的看出问题:

  1. 如果把merge commit撤销,那原本从dev合并过来的提交也会被撤销。
  2. 如果把代码回退到Dev commit 2,就会把原来在master上的两次commit也撤销了,就好像master分支变成了dev分支了。

当然这也是可以理解的,因为本来merge的信息就是由新创建出来的merge commit记录的,那么现在的两个操作就相当于把这个信息撤销了,理所当然的当前分支只能保留信息只能是你想要回退的分支的信息了。

总结

这两个命令没有优劣之分,完全看自己的需求和使用习惯。

从上面的分析来看:这两个命令的功能是一样的都是用来合并代码,但是对于使用场景来说:

  1. merge致力于保存现场,基本上是完整的记录了提交的过程。但是要注意的是,如果想要通过回退的方式检查提交记录,可能会与自己想象的不太一样。
  2. rebase则能使提交的过程保持分支树的整洁,省去了merge commit,而且可以使得回退的时候不会出现莫名其妙的问题,但是它会改变提交的历史记录。

注意:为了能有更好的演示效果,测试的过程中都没有考虑提交冲突的情况,如有疑问自行解决。


猜你喜欢

转载自blog.csdn.net/weixin_38056448/article/details/83187618
今日推荐