为什么Git执行分支合并时出现隐式合并、代码重复的异常问题?
问题核心原因
- 行尾符(EOL)配置冲突
这是该类问题最高发的诱因。大概率你同时启用了Git的自动行尾转换规则与Visual Studio的项目行尾配置,二者规则不统一。比如Git全局配置core.autocrlf=true自动转换Windows格式CRLF为Unix格式LF提交,但VS给项目配置了强制保留CRLF,导致两个分支的同一份代码实际行尾符存在差异:Git做diff时识别为不同内容,出现无差异代码报冲突的情况;合并时又因为行尾转换逻辑混乱,把同一段代码识别为两段新增内容直接拼接,就会触发if块重复、函数重复的问题。 - 合并基准(merge base)异常
如果你的分支历史存在过错误变基、硬重置后强制推送、或是意外合并过旧版本提交的情况,Git自动识别的合并基准会偏离两个分支的真实分叉点,指向更早的历史提交。此时Git会把分叉后已经合并过的代码判定为全新变更,直接追加到目标分支,就会出现代码重复、甚至冒出数周前旧版本代码的问题。 - 合并策略/驱动配置错误
你可以先执行git config --list检查是否配置过自定义合并驱动,或是给特定代码后缀设置了错误的合并规则,比如把代码文件识别为二进制文件合并、启用了存在问题的第三方合并工具规则,也会导致静默合并错误。
解决方案
- 统一行尾符规则
首先关闭存在歧义的自动行尾转换:
git config --global core.autocrlf false
在项目根目录新增.gitattributes文件,明确指定所有文件的行尾规则,示例:
*.cs text eol=crlf *.js text eol=lf *.json text eol=lf
配置完成后执行以下命令刷新本地文件缓存,消除存量行尾符差异:
git rm --cached -r . git reset --hard
- 修正合并基准
执行命令查看两个分支的真实分叉历史,确认合并基准是否正确:
# 查看分支分叉图 git log --graph --oneline master 你的开发分支名 # 查看Git自动识别的合并基准 git merge-base --all master 你的开发分支名
如果合并基准指向了更早的错误提交,不要用默认合并逻辑,改用变基整理开发分支后再合并:
git checkout 你的开发分支名 # 把开发分支的所有提交移到最新master之后 git rebase master # 再切回master执行合并 git checkout master git merge --no-ff 你的开发分支名
- 合并时禁用自动优化规则
合并时不要用VS的可视化合并工具,改用Git命令行加patience合并策略,提升大块代码场景的合并准确率:
git merge --no-commit --no-ff -X no-renames -X patience 你的开发分支名
合并完成后不要直接提交,先执行git diff检查所有变更,确认没有异常再提交。
4. 校验文件编码
确认两个分支的同一份文件编码规则一致,避免出现UTF-8带BOM和不带BOM的差异,编码不一致也会导致Git diff识别异常。
内容的提问来源于stack exchange,提问作者tiffanie
相关产品推荐
相关产品推荐

