Bootstrap

🏆【Git 实战专题】你知道git rebase如何让代码提交变得清晰明白吗?

什么是rebase

在介绍 rebase 之前,需要提前说明,rebase 是一个非常强大的功能,也正是因为它的强大,所以使用起来也有一定的隐患,一旦使用不好可能会对团队的代码造成非常大的问题。所以在使用前一定要了解其中的原理并小心谨慎的使用。

rebase 的功能可以简要的概述为对某一条线性提交分支上的记录进行编辑、删除、复制、粘贴、合并。合理使用 rebase 可以使团队的提交记录变的非常干净整洁。

注意:如非迫不得已不要通过 rebase 对任何已经提交到公共主干分支上的提交记录进行 commit!

使用rebase替代 merge 进行主干/开发分支合并

假设我们在开发的时候同时拉出来两个分支并行开发,然后有一条已经合并到主干分支 了,像这样:

这个时候我们想要把主干分支 的代码再合并到当前开发分支 ,然后再进行提交,如果使用merge 会是这样:

如果当前分支有很多的子分支,到最后合并的时候就会出现像一开始那张图一样爆炸的情况。

而如果使用 (或者 / )合并 分支,提交记录就会变成这样:

这样清晰明了。

注:使用rebase合并主干分支时,当前分支所做的修改永远会被认为是最新的,所以会导致在提交记录上就算 分支一开始的提交时间在 之前,但是 rebase 之后 commit 记录也是最新的,这也是rebase的初衷之一,更清晰的显示出来在什么时候提交到主干的什么功能(因为按照提交时间来看,分支的功能是在 分支功能合并到主干 分支后添加的)。

⚠️ 正是因为它改变了历史,所以我们更应该谨慎使用

当然,如果该分支是测试环境或者预发环境分支,则一般需要使用来合并。因为在这两个分支上会存在多个分支但是并没有合并到主干的修改。

再看一种情况:

如图所示, 分支其实是从 分支的 节点拉取出来的,而此时 分支并没有合并到主干 分支,但是 分支上的功能要提前合并到分支上,合并完成之后将 与 独立,变成两个互不相干的分支,这种情况下可以使用

可以看到这种情况下 与 已经互相独立互不相干了,而且 的记录线已经跟 在同一条线上了 * *不过在正常开发情况下应该避免这种情况发生,因为中已经包含了一部分的 变更,所以当 分支再合并主干的时候,可能会有许多冲突

我们在使用 或 合并的时候可能会有许多冲突

  • 在发生冲突时,将停止在第一个有问题提交,并在树上留下冲突标记。我们可以使用定位标记(<<<<<<),并进行编辑以解决冲突。

  • 对于编辑的每个文件,需要告诉 Git 冲突已解决,通常使用手动解决冲突并更新到对应的索引,

  • 之后,我们可以手动进行下一步进程

  • 我们也可以手动撤销rebase

4. 使用 rebase 编辑 commit

rebase 最经典的功能,就是编辑 commit。比如在 pull requests(gitlab为merge request)中需要修改代码的时候,需要把修改的内容合并到已经提交的commit上。

这里我们可以使用 来编辑提交记录,其中的意思是交互的意思,即弹出交互式页面供使用者编辑。和指的是编辑的开始和结束节点(不包含节点,范围逻辑是),如果不指定则结束节点会指向所对应的节点(一般使用的时候也不指定结束节点...)。

举个栗子:

此时我们想编辑分支的最新三条历史记录,我们可以使用前面所说的

或者是 ,我们会看到如下页面:

指令说明:

p 或 pick 		使用该commit,不做修改(默认指令)
r 或 reword 	使用该commit,但是修改它的commit信息
e 或 edit 		使用该commit,但是要停下来修改(commit信息和提交内容)
s 或 squash 	使用该commit,但是将此条commit融入之前的commit
f 或 fixup 	跟squash一致,跟前一条commit合并,但是丢弃该commit的日志消息 
x 或 exec 		运行shell命令(该行的其余部分)
b 或 break  	到此为止(稍后继续使用 'git rebase --continue' 进行rebase)
d 或 drop		丢弃该commit
l 或 label		使用label标记当前HEAD
t 或 reset		将HEAD重置到label标记
m 或 merge 	[-C  | -c ] 

在该页面点击键进入编辑页面,即可在指令模块编辑,编辑完成后点击然后输入保存并退出进入下一步操作。

一般来说,除默认的之外,最常用的就是、、、这几个命令了,这里就只详细的讲解以上命令。

4.1 reword

如果我们想要修改 这条commit的提交信息,只需在该条之前写明 或 方法:

保存退出之后进入commit编辑页面:

修改并保存之后,在提交记录里可以看到本地 记录已经被修改成了 ,如果后面还有分支存在修改,则使用 命令进行之后的修改,待所有commit都修改完成之后再使用 或 强制推送代码覆盖远端后,远端的提交记录就变成了:

可以看到提交记录已经被修改了。

4.2 edit

使用该方法之后,我们就可以修改想要修改的内容,修改完并执行 之后,就可以调用

来修改commit的记录内容,这里可以看到edit之后修改的文件是 README.md,

然后修改 commit 方式跟 一致,待所有 commit 都修改完成之后,使用 强推至远程便可以实现记录内容的编辑修改了。

4.3 squash

字面意思,使用 是将记录压缩到一起,一般用于一个大功能开发完成后合并提交到主干分支上使用,这里我们可以用 vue 的提交记录举例:

可以看的出来 记录下合并了许多子记录,这样也可以清晰的表明一个迭代的功能及开发提交记录。

4.4 fixup

也是将代码进行保留并合并到上一条提交记录,唯一的区别就在于 的记录被删除,此方法适用于我们在 MR 时候的 comment 修改。

注:如果我们在 rebase 的过程中因为一些原因退出了终端中断了 rebase,我们可以回来继续使用 进行继续编辑。