一、问题场景

我司使用 GitLab 进行代码管理,当我对系统进行 SpringBoot 2.0 的版本升级,分支已经 Merge 到 Master 分支。实际部署中发现依赖的某个二方包的子依赖未做升级,导致某个服务无法掉通。由于二方包的修复需要时间,为了不影响后续其他功能的发布,因此决定对 Master 分支进行 Revert。

等到第二天,当修复了那个二方包问题后,重新提了 Merge 申请,却发现提交变动只有对二方包的变动,其他的代码变动都没有了。

二、问题复现

下面模拟复现下这个问题,我创建了一个全新的项目。在 Master 分支做了首次提交,提交内容为:

First Commit From Master

gitlab提交mergeRequest_解决方案

然后创建一个新分支 dev,在提交内容后面追加了以下内容:

Second Commit From Dev

gitlab提交mergeRequest_解决方案_02

将 dev 分支 merge 到 master 分支,此时 master 分支内容如下:

First Commit From Master

Second Commit From Dev

此时我觉得 dev 分支还没有修改完毕,想要 revert 后重新提交。因此在 GitLab 中找到那个 Merge 申请,并点击 Revert 按钮,如下图所示。

gitlab提交mergeRequest_git_03

点击 Revert 后相当于将代码 Revert 到了一个新分支,并将那个新分支 Merge 到 Master 上。Commit 记录如下图所示,其中的 revert-f8856e36 就是那个 revert 分支。

gitlab提交mergeRequest_代码管理_04

Revert 后切换到 Master 分支,发现代码的确已经回滚了。

gitlab提交mergeRequest_git_05

此时切换到 dev 分支,在最后再填上一行内容,内容如下:

Third Commit From Dev

gitlab提交mergeRequest_代码管理_06

然后重新对 dev 分支发起 Merge 到 Master 的申请。

gitlab提交mergeRequest_git_07

但是发现 dev 分支和 master 分支的差异 commit 只有 dev 分支 revert 后的提交记录。

gitlab提交mergeRequest_代码管理_08

再切到 Changes页面,发现变动也是只有 revert 后的变动记录。revert 前的 Second Commit From Dev 这行内容竟然不算改动,被认为已经存在于 Master 分支上了?

gitlab提交mergeRequest_git_09

但是切换回 master 分支,Second Commit From Dev 这行内容的确已经被 Revert 了。

gitlab提交mergeRequest_代码管理_10

以上就完成了对问题的复现,Second Commit From Dev 这行内容就丢失了,准确说就是 dev 分支 revert 之前的内容都丢失了。

三、解决方案

通过参考以下文章获得了解决方案:

核心思想就是对 revert 的那次提交记录再次进行 revert,下面开始实验。

首先切换到 Master 分支,并基于 Master 分支拉出一个分支 revert_tmp,这个分支的作用是用来保存 revert revert 的提交记录的。

~/Projects/demo: git checkout -b revert_tmp

找到 revert 的那条提交记录,注意了,revert 相关的会有两条记录,第一条是 revert,第二条是 revert 后 merge 的记录,这里取第一条,如下图所示。

gitlab提交mergeRequest_git_11

~/Projects/demo: git revert f5c3b544164eec662ea6914d6bd19aedf46874f8
[revert_tmp aea128e] Revert "Revert "Merge branch 'dev' into 'master'""
 1 file changed, 3 insertions(+)

然后切换回 dev 分支,将revert_tmp 这个分支 merge 到 dev 分支上。

~/Projects/demo: git checkout dev
~/Projects/demo: git merge revert_tmp
~/Projects/demo: git push

将 dev 分支推送到远程后,重新提交对 master 的 merge 申请。我们发现,在 revert 之前的提交记录还没有找回来,即 second commit by dev 这条记录没有找回来,如下图所示。

gitlab提交mergeRequest_git_12

这是因为 revert 的特性所致,虽然这条提交记录没有找回来,但是 revert 之前的代码都回来了,如下图所示。

gitlab提交mergeRequest_代码管理_13