OverRainbow

Fix Git Merge Mis-Deleting files

☕️ 1 min read

你可以从本文了解到

背景

看到了一片其他团队的关于冲代码的文,这篇文章做了一些分析和定位问题,但是没有给出特别好的拯救办法。本文结合实际经验,进行补充。

咱们有一个项目,有很多人在不同的分支上开发。有一天,A 同学提交了一个 merge 提交,这个 merge 把其他人的代码删除了。在不知道的情况下,大家又默默开发了好几天。

最后,这个问题被发现了,然后大家很着急,不知道该怎么还原被删的代码。

问题分析和方案比较

首先,为什么提交前后代码都可以编译通过呢?

1、A 在开发的时候,肯定代码是可以跑的。 2、merge 合入主干后,别人的代码被删了,理论上,也有一定概率可以跑的(被删的代码是静态资源或者没有被什么依赖到)。

然后,回到灾难现场。现在的 git 提交是个什么情况呢?

简化成如下,a比b少了一堆文件

a [merge 节点]
|\ b
| |c

假如a提交是一个普通提交,那么我们只需要revert a提交即可。

但是a这个merge提交不携带任何信息,不能revert。该如何修复呢?

有很多方法,不同的方法复杂度不一样。其中咱们采用的是如下的方法。其思路如下。

1、求出b从a删除的文件

2、并把他们加回来,提交,解决冲突。

其中1这个步骤我们可以以一种反向思维去做。先git checkout到b,然后git reset --soft到a,这样,工作区就出现了被删掉的文件,直接将其提交即可。

这是什么原理呢?我们这样来理解一下。

首先,假如先checkout到a,然后reset到b,那么工作区暂存的就是b删掉的文件

咱们反过来操作,先checkout到b,然后reset到a,那么工作区暂存的就是revert b删掉的文件即加回来这些文件。

其实,reset —soft做了什么呢?

reset --soft 会在重置 HEAD 和 branch 时,保留工作目录和暂存区中的内容,并把重置 HEAD 所带来的新的差异放进暂存区。

理解了这句话。差异是before - after。那么我们带入a和bbefore:b, after:a,这个差异就是b-a=被删的文件加回来

步骤2的操作可以用git pull -r将本地提交追加到最新,并解决冲突即可。

反思

1、预防:CR要仔细,发现有大量文件别通过,仔细核对。

2、错误已经发生,要沉着冷静。有时候正向走不通,可以考虑反向操作,会有意想不到的效果。