记录一次 git 回滚的坑爹体验

96
nanchen2251
0.5 2018.09.03 22:06* 字数 1575

Git 如何遗弃已经 push 的提交,处理方法应该更新到文章:Git 如何遗弃已经 Push 的提交

以下是原文:

最近也是终于开启了代码编写之旅,我只能默默地说一句,写代码的感觉,简直不能再爽!

不过也由于 git 的分支管理蛋疼懵逼很久,所以必须记录以及和大家分享一下本次坑爹的旅行。

写在前面

每个公司相比都有自己的 git 分支管理规范,在项目组中开发人员较多的时候,这个就显得尤为重要。所以我们必须得掌握 git 的分支管理。基本套路就是有一个主线,然后在迭代周期內,每个开发人员拉取自己的分支,待开发完毕后大家再 merge 回主线,发布版本。

流程图

具体的 git 代码分支管理看这个好了:https://nvie.com/posts/a-successful-git-branching-model/

怎么回事?

到底怎么就被 git 版本回滚给坑了呢?不急,待我慢慢道来。

在咕咚的项目组中,在一个新的需求评审完毕,进入开发状态时,大家会基于 develop 分支拉取自己的分支,命名为 feature/XXX,然后各自在自己的分支上进行开发。

由于大家开发业务上的不同,所以在需求开发完毕,整合代码的时候,一般都不会出现冲突的情况,即使出现,那也应该是比较容易解决的。

可在最近的一次 merge 中出现了一个比较奇怪的问题。

如图所示:

1.png

我当前所在的分支是 feature8.29.0_nanchen,该分支已经 merge 了 release8.28.0 分支上的最新代码,本地没有任何提交。现在由于一些原因,我需要把另外一位同事开发的 feature8.28_buyGifts 分支代码合并到我的分支上。进行开发。

意外地出现了很多的冲突。

2.png

我们使用 git status 看看到底发生了什么。

3.png

从截图中可以看出,git 认为我们当前的分支 delete 了不少文件,而这些文件是在 feature8.28_buyGifts 分支上存在的。

我们 vim 查看文件情况。这里就选取第一个 MarketItemsInfo.java 做截图。

4.png

我们查看其他冲突文件以后,发现全部是和 Presents 这个类相关的冲突,而这些文件实际上是开发 feature8.28_buyGifts 分支的小伙伴开发的,主分支不可能做干预,这里让人什么疑惑。

为了验证自己的猜想,我们查看一下 MarketItemsInfo.java 的提交历史。

5.png

正如我们所想,确实在 7 个月内,都没有人动过这个文件。

所以一个 7 个月都没有人动过的文件,怎么就会 merge 的时候出现了这个令人费解的冲突呢?

查看一下当前分支所有的日志。

6.png

似乎发现了一点异常。这位小伙伴曾经往 release8.28.0 进行了 merge 操作,此后被告知未提测不能 merge 到主线的时候,他又对 release8.28.0 分支做了 revert 操作。所以可能因此让 git 认为 release8.28.0 上有了这样的文件修改,因为操作后面被 revert,所以用 git lg <fileName> 的时候,也看不到最近对文件的改动记录。

我现在只能说可能是这个原因,如果大家有高见的还望留言指导。

如果是这样,那么我们只要在此次 revert 操作之前进行 merge feature8.28_buyGifts 分支代码的话,应该是不会出问题的。

为了验证,我们重新建立一个分支,然后 reset 到 revert 操作之前,再进行 merge,查看是否还会出现这样的情况。

7.png

明显没有出现任务冲突。

我们再试试,在 revert 后进行 merge 操作。

8.png

如我们所想,当我们 reset 到 revert 提交的时候,再进行 merge 直接发生了这个冲突。

这样的话,一定意义上,已经印证了我们的想法。git 确实把这个文件当做修改了。

怎么处理?

遇到了这样的问题,直观上,肯定是将冲突的改动,全部以这位小伙伴的代码为准,因为主线上的代码,已经确认是没有人动过这几个文件的。

最不济的方法,可能就是直接舍弃掉这个小伙伴的操作,然后强行把他后面写的代码,重新写一遍了(因为他后面的代码量很少)。

为什么会出现这个 revert 操作?

说到底还是此次 revert 惹的祸。

我询问该小伙伴后,得知,他是在 release8.28.0 主分支上 merge 了自己的代码,并且 push 到服务器后,被告知未提测的代码不能 merge 到主分支后,希望遗弃 push 到服务器上的这个 merge 操作,所以才采用 revert 命令的。

正确的操作?

我写这个正确的操作题目,是真的不敢写的。不过还是斗胆写了一下。如果我想遗弃自己 push 到服务器上的提交的话,我一定会选择 reset 后再进行 push 操作的。

  1. 首先使用 git reset —hard <版本号> 让 HEAD 指针指向 merge 前的 commit ID。(注意,这是直接放弃之后所有的提交,采用 --hard,这里因为是没有别人提交别的代码)
  2. 再使用 git push origin <分支名> —force 命令强行把提交 push 到服务器即可。

写在最后

实际上,我自己对 git 的操作也有些模棱两可,不过还是希望能用本次教训给大家简单做下交流吧。

Android
Web note ad 1