Git合并识别目录重命名致覆盖 如何在单仓库管理多版本代码?
你碰到的合并异常本质是Git的三方合并默认开启重命名检测:当Git发现两个分支中文件内容相似度超过阈值(默认50%),就会判定为路径重命名,自动把开发分支的改动合并到被判定为重命名后的目标路径(也就是你Release分支里的v1目录),不会保留原dev路径创建新文件。你最初设想的「用专门分支存放所有版本代码」是完全可实现的,不需要切换到仓库外手动管理的方案,下面是可直接落地的方案:
你不需要推翻原来的Dev/Release/Main分支设计,只需要调整Dev合并到Release的操作逻辑,绕开重命名检测即可,操作步骤如下:
- Dev分支功能开发完成后正常打版本tag
- 切到Release分支,不要直接执行
git merge Dev,先执行命令直接拉取Dev分支的开发目录到当前分支:
# 确保当前工作区无未提交改动 git checkout Dev -- app/src/api/dev/
- 命令执行完成后,Release分支会原样新增来自Dev的
dev目录,原有v1目录不会有任何改动 - 正常执行你的目录重命名、namespace替换脚本,把
dev改为对应版本号(比如v2)后提交,再合并到Main分支即可 - 后续发v3、v4版本重复上述流程即可
如果你想保留merge的操作习惯,也可以在合并时加参数关闭重命名检测:
git merge -X no-renames Dev
该参数会强制Git严格按文件路径合并,不会自动识别重命名,Dev分支的dev目录会被完整新增到Release分支,不会改动已有v1目录的内容。
不建议在Git仓库内长期存储多份重命名后的版本目录,会带来额外的仓库体积膨胀、代码冗余问题,更通用的方案是把版本转换逻辑从Git提交流程移到部署环节:
- 仓库内只维护Dev分支的单一开发版本代码,永远保留
dev目录结构,不做分支内的目录重命名操作 - 开发完成后正常打版本tag即可,不需要维护Release、Main分支的多版本目录
- 写一套固定的部署脚本:发版时拉取对应tag的代码,自动完成目录重命名、namespace替换,直接输出到生产环境的对应版本目录
你之前考虑的仓库外手动管理本质就是这个方案的手动版本,把手动操作写成自动化脚本后,既不会碰到Git合并的重命名问题,也不会出现手动复制的人为失误,一次配置后所有发版流程全自动。
如果你确实需要在Git仓库的同一个分支内留存所有历史版本的代码,可以直接在Dev分支完成版本固化:
- 某个版本开发完成后,直接在Dev分支把
dev目录全量复制为对应版本号目录(比如v2),提交后打tag - 之后直接在
dev目录上继续开发下一个版本的内容
这种模式下所有版本目录的提交记录都在Dev分支明确存在,不管怎么合并都不会触发Git的重命名误判,所有版本目录会完整同步到Release、Main分支。
内容的提问来源于stack exchange,提问作者Merricat

