Git以旧版本覆盖新变更并删文件:develop分支合并异常原因排查
这种情况我之前在团队协作里碰到过好几次,结合你描述的场景,大概率是以下几个原因导致的,咱们一个个拆解:
1. QA合并的分支是基于过时的develop快照创建的
这是最常见的根源:你的同事从develop拉取特性分支后,develop本身已经累积了不少新提交(包括和你分支相关的变更),但同事的分支一直没同步最新的develop。最后QA直接把这个过时分支合并回develop——这相当于把develop的状态强行“回退”到了同事分支创建时的旧版本,顺带删除了develop后续新增的大量文件。当你合并这个被“回退污染”的develop到自己分支时,Git会默认认为develop的状态是“权威”的,从而用它的旧内容/删除操作覆盖你分支的新变更。
你可以用这条命令快速验证:
git log --oneline --graph develop
看QA合并的那次提交是不是带着大量文件删除,且提交历史呈现“分叉后突然反向回退”的形态。
2. 合并时误使用了错误的冲突解决策略
如果在合并流程中,有人(包括你自己)不小心设置了全局或局部的合并策略,比如默认用theirs(即develop的版本)解决所有冲突,就会导致你的分支变更被全盘覆盖。比如之前有人执行过:
git config merge.defaultToTheir true
或者合并时误加了-X theirs参数,都会让Git直接优先采用develop的版本,哪怕你的分支有更新的内容。
3. Git的重命名检测误判
如果你的分支里对某些文件做了重命名操作,而develop里直接删除了原文件名,Git的自动重命名检测可能会误判为“你分支保留了旧文件,develop删除了它”,从而在合并时执行develop的删除操作,连你重命名后的新文件也一并干掉(因为Git认为新旧文件是同一个实体)。
如何修复当前问题+避免再次发生
修复当前分支
- 先暂停操作,用
git reflog找回你分支合并前的状态并恢复:
git reflog # 找到合并develop之前的commit哈希值,比如abc123 git reset --hard abc123
- 重新合并develop,但手动控制冲突解决:
git fetch origin git merge origin/develop
遇到文件删除类冲突时,用git checkout --ours <文件名>保留你分支的文件,或者用git mergetool可视化处理冲突。
避免未来再出现
- 强制要求特性分支合并前同步最新develop:让同事在提交PR/合并前,先执行
git rebase origin/develop,把自己的分支基于最新的develop重新提交,从根源避免过时分支污染主分支。 - 给develop设置分支保护:禁止直接push或合并未经过代码审查、未同步最新develop的分支,确保每一次合并都有清晰的历史可追溯。
- 合并时使用
--no-ff参数:生成明确的合并提交,后续排查问题时能一眼看清合并的上下文。 - QA合并前做快速校验:合并前先查看提交的变更内容,如果有大量文件删除,一定要确认是预期内的操作,避免误合并过时分支。
内容的提问来源于stack exchange,提问作者user923

