请教一个诡异的 git 问题

6 小时 53 分钟前
 wind3110991

事情的背景是,本人在开发中本地 feature 分支,git commit 了一个改动,commitid = 11111

然后执行 git merge origin master 到本地,生成了一个 MR commitid = 22222 此时:有 20+个文件修改合并到了 feature 分支

再执行了一波 git push origin feature 推送到远端。

此时,觉得好像修改整体有点问题,于是脑抽地执行了 git revert -m 1 22222 ( merge commit )

手动调整了一个 A 文件,再次 git commit ( commitid = 33333 ) 然后重新执行了 git push origin feature

于是我去 MR 到 master 了,此时按惯例检查 change list 并没有发现异常,MR 提示只有我修改的这个文件 A ,我便将这个文件 MR 到了 master 。

事情看起来好像没有什么不对,我以为回退了问题代码,并且 MR 检查 diff 也没问题,但是过了几天线上出问题了。。。有人陆续找我说自己 master 的代码“消失了”

检查了下,发现 checkout 到 master ,这 20+个文件的修改被“回退”了,而且 master 分支上有一个单独的 commit 记录:

Revert "Merge remote-tracking branch 'origin' into feature"

This reverts commit 22222, reversing
changes made to 33333.

紧急一顿通知恢复处理,评估影响+道歉。

事后回顾了下,有个比较大的疑点:为什么最后一次 MR 时,diff 里并没有提示 20+ 个文件实际发生了改动,而只 diff 出我 revert 后的这个文件 A 的改动,导致我没有及时发现 diff 有问题。

AI 分析了一波,结论大概是:

MR 合并时,Git 使用的是 三方合并( 3-way merge )

master:   A --- B --- C
                \       \
feature:         M --- R --- .proto fix


合并时 Git 的逻辑是:

    base:master 和 feature 的共同祖先
    master:没变
    feature:有 revert commit ( R )

👉 Git 看到的是:

    “feature 分支主动撤销了这些改动”

于是合并结果就是:

✅ 这些改动在 master 上也被撤销了

也就是说:

    feature 的 revert ,通过 MR 把 master 的内容给“反删了”
    
为什么 MR diff 里“看起来没事”?


原因是:

    MR diff 是 最新状态对比
    feature 上的 revert ,对 Git 来说:
        ✅ 不是“删除文件”
        ✅ 而是“对齐 master 并取消 merge 引入的差异”

这是 revert merge commit 最隐蔽、最危险的地方

看完分析,我依然觉得 git 这样设计很不合理。。。MR 不应该整体按照 feature 和 master 分支所有 commit 后,最终的 diff 来 MR 么?

253 次点击
所在节点    程序员
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1221173

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX