Git重命名冲突本质是文件身份连续性丢失,因Git仅识别删除+新增而非重命名,导致merge时出现deleted by us/added by them等状态冲突,需用git mv规范操作并配合--follow诊断历史。

git mv 没用,直接改名后 merge 就报冲突
Git 不知道你重命名了文件,它只看到:原文件被删了,新文件被加了。一旦另一个分支还在修改旧文件,merge 时就会提示 deleted by us 或 added by them —— 这不是代码行冲突,是文件状态冲突。
补救方式有限,但最稳妥的是回退到重命名前的状态,改用 git mv:
- 确认当前没提交:
git status显示 “deleted: old.txt” 和 “untracked: new.txt” - 撤回删除操作:
git restore --staged old.txt && git checkout old.txt - 再执行重命名:
git mv old.txt new.txt - 立刻提交:
git commit -m"rename old.txt → new.txt"
注意:如果已经提交过手动重命名,就不能简单 restore,得用 git revert 或交互式 rebase 撤掉那条提交,否则历史里仍存“删除+新增”的断裂记录。
两个分支各自重命名了同一个文件
比如 A 分支把 config.py 改成 settings.py,B 分支改成 app_config.py,合并时 Git 完全无法关联,会同时报出两份“added”和一份“deleted”,最终卡在 conflicted 文件列表里。
这时不能靠编辑冲突标记解决,因为冲突不在代码行,而在文件路径层级:
- 先运行
git status,确认哪些文件被列为both added或deleted by us - 手动决定保留哪个新名字(比如选
settings.py),然后删掉另一个:git rm app_config.py - 把内容从删掉的文件复制进保留的文件(仅内容,不带 Git 历史)
-
git add settings.py && git commit,完成解决
后续要避免这类问题:重命名前先同步目标分支,或在团队内约定重命名需提前沟通、统一 PR 标题打上 [rename] 标签。
CNB 云原生构建平台的 Git 操作技能,支持代码克隆、提交、推送、分支管理、Merge Request 管理、流水线触发与结果读取。初次使用需收集用户的 Git 用户名和邮箱。
重命名 + 同时修改内容,合并时标记满屏
这是最易误操作的场景:你用 git mv 重命名了 utils.js,又顺手改了几行函数逻辑;而另一分支没动文件名,但改了同一函数——Git 会把重命名当作“移动”,再叠加内容修改,最终在 utils.js(旧名)或 helpers.js(新名)里打出三段冲突标记,其中一段还标着 renamed from utils.js。
关键点在于:Git 的 rename detection 默认开启,但只在 diff 阶段生效,merge 时不一定能连贯识别。所以:
- 别依赖 Git 自动关联重命名后的修改,尤其当改动量大时
- 提交前用
git diff --find-renames HEAD~1确认 Git 是否真识别出了重命名 - 如果
git show里看不到similarity index 90%这类提示,说明 Git 没当成 rename,实际还是按 delete+add 处理 - 这种情况下,建议拆成两个提交:先
git mv+ 提交,再改内容 + 提交,降低 merge 复杂度
用 git mergetool 也救不了的重命名冲突
VS Code、TortoiseGitMerge 等工具对纯文本冲突很友好,但遇到重命名冲突时,它们常把两个“不同名”的文件当独立实体打开,根本不会并排显示旧名/新名的内容差异。
真正有用的不是图形工具,而是 Git 自带的诊断命令:
-
git log --oneline --name-status --follow new_name.txt:看 Git 是否还认得这文件的历史 -
git show :0:new_name.txt和git show :2:old_name.txt:分别提取 merge 基础版本(stage 0)和对方分支版本(stage 2)内容,手动比对 -
git checkout -m --ours -- new_name.txt或--theirs:快速检出某一方完整内容,再人工合并
重命名冲突的本质不是“不知道怎么选”,而是“Git 已经丢失了文件身份连续性”。修复成本随提交距离线性上升——越早发现、越少中间提交,越容易拉回正轨。

















