跳到主要内容

5.4 变基的使用和注意事项


在 Git 中整合来自不同分支的修改主要有两种方法: 合并(merge) 和 变基(rebase)。 在本节中我们将学习什么是“变基”,怎样使用“变基”,并将展示该操作的惊艳之处,以及变基的使用场景。

什么是变基?

分支管理中我们讲到过,整合分支的最容易方法是 merge 命令。它会把两个分支的最新快照以及二者最近的祖先进行三方合并,合并的结果是生成一个新的快照并提交。

其实还有一种方法,可以把分支 b 的所有更改在 a 的基础上应用一次,然后把应用后的结果放到 b 里面,这种方法叫做“变基(rebase)”。你可以使用 rebase 命令把某一分支上的所有修改都复制到另一分支上,就好像重新播放一样。

“变基”通俗理解就是改变某个分支所基于的分支。

变基当前分支

变基使用 rebase 命令,用法如下

git rebase 新基于的分支名或commit

如果你的当前分支是基于 master 分支的 c2 提交分出的分支 a ,在 mastera 分支都有提交的内容,那么你的提交记录图应该是下图 1 这样的。 amaster 都在自己单独的一条线上,由于 c5c3 的基础(父对象)都是 c2 ,所以 c3c4c5 是平行的。

原始情况

当你执行了正面的命令以后,你的提交记录会变成下图 2 这样。

git rebase master

执行过变基以后, a 分支中的提交 c3 和 c4 被放到了执行时 master 的最新提交 c5 后面。正如“变基”其名一样, a 的基础被改变了。 a 在一开始的基础提交为 c2 ,变基后变成了 c5

变基后

变基其他分支

直接使用 git rebase 新基 会把当前分支进行变基。还可以使用下面的命令对指定的分支进行变基。

git rebase 新基 目标分支

比如下面的命令可以和上面的命令达到同样的目的。

git rebase master a

唯一的区别在于, git rebase master 需要你当前活动的分支是 a ,而 git rebase master a 则可以在处于任何分支的情况下自动切换到 a 并把 a 变基到 master

变基到父对象的父对象

在这样一个场景里面:

有一个需求 a

你已经在分支 ba 中开发了,并且已经产生了一些提交。

但这个时候项目经理发现另一个需求 b 和需求 a 有相似的地方。

于是要求把需求 b 和 a 放到一起做,于是你基于分支 ba 创建了一个新分支 bb。

过了一段时间。。。。

项目老大:需求 a 和 b 做完了吗?

:b 做完了,a 还没有

项目老大:先上 b,a 先不管

:。。。。

这个时候你会怎么办?

把分支 bb 直接提测吗?不行,因为 bb 是基于 ba 创建的,而在创建的时候 ba 已经有了一些关于需求 a 的提交。

新建一个分支,手动把需求 b 的代码,复制过去吗?别人可能会这样做,相信学过我的《Git 进阶教程》的你肯定不会这样做。

使用上面的知识,把 bb 重新变基到 ba 创建时的提交是可以的,但如果这个时候你在 ba 和 bb 都有了几百个提交呢。

其实这种情况下要解决是非常简单的,只需要一行命令就可以搞定。

当然,为了防止项目老大再次变卦,可以把 b 分支给备份一下。

git rebase --onto master bb ba

只需要执行上面的代码,你就可以把 master 分支以及 ba 和 bb 共同祖先之后的 ba 里面存在但 bb 里面不存在的提交放到 ba 里面“重放”一遍,如果有冲突,处理一下冲突就可以搞定。

有冲突时变基进程会暂停,处理过冲突以后使用 git rebase --continue 继续执行变基,或者可以使用 git rebase --abort 取消操作。

当别人还在苦苦查看提交记录或重新复制代码的时候,你已经搞定了,这多出来的时间当然就可以用来摸鱼学习了。

慎用变基

既然变基这么好用,为什么要慎用呢?

会让团队协作代码变的混乱

我之所以把 merge 放到基础里面讲,而把 rebase 放到进阶里面,就是因为 rebase 虽然执行起来和 merge 一样简单,但 rebase 并不适用于所有场景。

比如下面这两种场景,最好就不要用变基:

  1. 你所变基的目标分支还有其他人在上面提交代码
  2. 你们团队的提交模式不是直接提交,而是 PR。

会破坏分支间的关系

在使用 merge 整合代码后,查看提交图可以看到分支间的关系和分支创建时机。而经过变基以后,提交图会变成一条线,无法清楚的展示出各个分支间的关系。

使用不当会毁掉整个分支内容

比如上面的命令 git rebase --onto ba bb ba1 ,如果在使用的时候把三个分支名的顺序给写错了,你可以把目标分支的内容给破坏掉。这个时候你就算再使用 reset 命令也无法还原到变基前的状态了。

该内容为何方原创,转载请注明本页地址
https://iamhefang.cn/tutorials/Git系列教程/git-tutorial-5-4-rebase