Git合并提示文件冲突但一侧分支自共同祖先起未修改该文件咨询
Git合并分支出现"deleted by them"冲突问题解答
问题背景
存在version-1.0和version-2.0两个分支,共同祖先为提交C。合并两个分支时提示文件a.txt存在冲突,复现操作与输出如下:
$ git checkout version-2.0 $ git merge version-1.0 $ git status Unmerged paths: (use "git add/rm <file>..." as appropriate to mark resolution) deleted by them: a.txt $ git ls-files -u | grep a.txt 100644 xxxxxxxxxxxxxxxxxx 1 a.txt 100644 yyyyyyyyyyyyyyyyyy 2 a.txt $ git --version # Git环境版本 git version 2.34.1.windows.1
通过git merge-base version-1.0 version-2.0获取到共同祖先提交C后,执行git diff --stat C version-1.0未发现a.txt存在变更,对应两个疑问:
- Git判定该文件产生合并冲突的逻辑是什么?
- 执行Git双分支合并操作时,如何获取更详细的过程信息?
问题1:该场景下的冲突判定逻辑
Git默认采用三方合并策略处理分支合并,会同时对比三个版本的文件状态:
- 阶段1(stage 1):两个分支共同祖先
C中的文件版本 - 阶段2(stage 2):当前所在分支(合并操作的
ours侧,即本次的version-2.0)中的文件版本 - 阶段3(stage 3):待合并分支(合并操作的
theirs侧,即本次的version-1.0)中的文件版本
你看到的deleted by them属于典型的修改/删除冲突,触发条件非常明确:
- 共同祖先
C中存在a.txt(对应git ls-files -u输出的stage 1记录) - 当前分支
version-2.0保留并修改了a.txt(对应输出的stage 2记录) - 待合并分支
version-1.0在提交历史中删除了a.txt(输出中无stage 3记录就是直接证据)
这种场景下Git无法自动决策:是保留当前分支修改后的a.txt,还是跟随待合并分支的操作删除文件,因此会将文件标记为未解决冲突。
至于执行git diff --stat C version-1.0未看到a.txt变更,属于命令使用的问题:--stat参数只输出文件内容变更的行数统计,排查文件存在性变更优先用--name-status参数,可以直接输出每个文件的变更类型(D代表删除、M代表修改、A代表新增),不会遗漏删除类操作。
问题2:获取合并详细过程信息的方法
- 合并时输出基础过程日志:执行合并命令时增加
-v/--verbose参数,即git merge -v version-1.0,会直接输出合并过程中的文件处理结果,包括自动合并成功的文件、触发冲突的文件及冲突类型。 - 冲突发生后查看三方文件状态:
- 执行
git show :1:a.txt查看共同祖先中的a.txt内容 - 执行
git show :2:a.txt查看当前分支中的a.txt内容 - 执行
git show :3:a.txt如果提示文件不存在,即可确认待合并分支侧已删除该文件
- 执行
- 核对两个分支相对于共同祖先的全量变更:
# 查看version-2.0相对于C的所有文件变更,含类型标记 git diff --name-status C version-2.0 # 查看version-1.0相对于C的所有文件变更,含类型标记 git diff --name-status C version-1.0 - 查看底层合并调试日志:如果需要排查异常的冲突判定,可以在执行合并命令前增加
GIT_TRACE=1环境变量,即GIT_TRACE=1 git merge version-1.0,会输出Git合并时执行的所有底层操作、决策逻辑日志,适合定位复杂合并问题。
内容的提问来源于stack exchange,提问作者Adooo
相关产品推荐
相关产品推荐

