请教一个诡异的 git 问题

wind3110991 2026-06-17 20:50 1

事情的背景是,本人在开发中本地 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 么?

最新回复 (4)
  • yuedashi 06-18 07:50
    1
    git revert -m 1 22222 这种高级用法,不理解啥意思,用毛啊。直接 git revert 111111 。不是通用的做法?
  • goodSleep 06-18 08:35
    2
    用不明白这种,我一般 rebase master ,保证自己分支只有自己改的东西
  • waterlaw 06-18 09:50
    3
    revert 命令不修改版本库的现存历史记录。相反它往历史记录中添加新提交。
    git revert 命令作用于全部提交,而不是文件。
    如果另一个开发人员已经克隆了你的版本库或获取了一些提交,那修改提交历史记录就有很多影响。在这种情况下,你可能不应该使用修改版本库中历史记录的命令。相反,使用 gir revert
  • wind3110991 楼主 06-18 11:01
    4
    @yuedashi AI 直接帮我执行的,我放权了的,然后 MR 时根本发现不了
* 帖子来源V2EX
返回