合并feature1至main遇冲突,git log --merge仅显单个提交的排查
尝试将分支feature1合并到main时出现合并冲突:
$ git status On branch main Your branch is up to date with 'origin/main'. nothing to commit, working tree clean $ git merge --no-ff feature1 Auto-merging setup.cfg CONFLICT (content): Merge conflict in setup.cfg Automatic merge failed; fix conflicts and then commit the result.
通常git log --merge会显示两个分支中修改冲突文件的提交,但这里只显示了feature1的提交:
$ git log --merge commit c01a640a5e6c9e4cb8560760aa1878f49534687f (origin/feature1) [...]
查看setup.cfg确实存在冲突:
<<<<<<< HEAD foo==3.45.0 bar==3.4.2 ======= foo==3.46.0 bar==3.6.0 >>>>>>> feature1
git blame显示main中foo==3.45.0来自提交b8d0b8b6(该提交是feature2合并到main的结果),而此前已经将feature2合并到feature1并解决了冲突,且main中涉及该文件的所有提交feature1都已包含。现在需要找出main中导致冲突的提交。
Update 1
在main分支执行:
$ git merge-base HEAD feature1 217f35342789e0a6c9b46e7eb4988e61cb6a7ba4
该提交是已合并到main的feature1旧提交,且未修改setup.cfg;设置merge.conflictStyle=diff3后的冲突显示:
<<<<<<< HEAD foo==3.45.0 bar==3.4.2 ||||||| merged common ancestors <<<<<<<<< Temporary merge branch 1 foo==3.45.0 ||||||||| baa2035 foo==3.41.0 ========= foo==3.43.0 >>>>>>>>> Temporary merge branch 2 bar==3.4.2 ======= foo==3.46.0 bar==3.6.0 >>>>>>> feature/CD-204-Detect-step-option-typos
Updates 2/3/4
分支历史:
git log --oneline --graph --decorate main feature1 feature2 feature3 * 0c85be0 (origin/feature1, feature1) Merge branch 'feature2' into feature1 |\ * | c01a640 [commit from 'feature1'] | | * 3f53bf5 (HEAD -> main, origin/main) Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 217f353 [commit from 'feature1'] | | * 67bee00 Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 70702f7 [commit from 'feature1'] | | * 93c8872 Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 2c80431 [commit from 'feature1'] | | * 323d2a1 Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 8a24b9b [commit from 'feature1'] | | * 19c2462 Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | d8c5679 [commit from 'feature1'] * | | d9ddb8b [commit from 'feature1'] | | * 1951b79 Merge branch 'feature2' into 'main' | | |\ | | |/ | |/| | * | b8d0b8b (origin/feature2, feature2) [commit from 'feature2'] | | * 1b4224e Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 96ba75d [commit from 'feature1'] | | * 88f122d Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 27b3e3a [commit from 'feature1'] | | * 5ff415a Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 07faa23 [commit from 'feature1'] | | * e0d54c5 Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 4b5d664 [commit from 'feature1'] | | * 6098d4d Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 04d9b9e [commit from 'feature1'] | | * e7586b1 Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 3d967c0 [commit from 'feature1'] * | | 387a3a3 [commit from 'feature1'] | | * 5d7fe99 Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | d5968c6 [commit from 'feature1'] | | * 567b71a Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 59b12e0 [commit from 'feature1'] | | * 7f7e3cc Merge branch 'feature1' into 'main' | | |\ | |_|/ |/| | * | | 3c403dc Merge remote-tracking branch 'origin/feature3' into feature1 |\ \ * | | | db64cb7 [commit from 'feature1'] | | | * cef6b50 Merge branch 'feature3' into 'main' | | | |\ | | |_|/ | |/| | | * | | de8a647 (origin/feature3) [commit from 'feature3'] | * | | a66b4ce [commit from 'feature3'] | * | | 820f80c [commit from 'feature3'] | * | | 88afa63 Merge branch 'feature2' into feature3 | |\ \ | * | | | cdd90f4 [commit from 'feature3'] |/ / / / | | | * 2c9c566 Merge branch 'feature2' into 'main' | | | |\ | | | |/ | | |/| | | * | f2c5d5c [commit from 'feature2'] | |/ / | | * 5148816 Merge branch 'feature2' into 'main' | | |\ | | |/ | |/| | * | baa2035 [commit from 'feature2'] |/ / [...]
Update 5
各分支setup.cfg相关内容:
- feature1最新提交:
$ git show 0c85be0c96e0b9cde0d03de9ce52ab7496347788:setup.cfg [...] foo==3.46.0 bar==3.6.0 [...]
- feature2最新提交:
$ git show b8d0b8b6bf1710b3a9d0833e0b613616b44d459c:setup.cfg [...] foo==3.45.0 bar==3.4.2 [...]
- feature3最新提交:
$ git show de8a64716a6a1f237202dbaf0347f9d077dc2dcb:setup.cfg [...] foo==3.43.0 bar==3.4.2 [...]
- main最新提交:
$ git show 3f53bf5ceea50b09692bc40d1c1943048f38c735:setup.cfg [...] foo==3.45.0 bar==3.4.2 [...]
- 合并基:
$ git merge-base main feature1 217f35342789e0a6c9b46e7eb4988e61cb6a7ba4
$ git show 217f35342789e0a6c9b46e7eb4988e61cb6a7ba4:setup.cfg [...] foo==3.43.0 bar==3.4.2 [...]
Update 7
发现main与feature1存在多个合并基:
# Original repo from my post, not the example from Update 6 $ git checkout main $ git merge-base --all main feature1 217f35342789e0a6c9b46e7eb4988e61cb6a7ba4 b8d0b8b6bf1710b3a9d0833e0b613616b44d459c
其中b8d0b8b的setup.cfg状态与main一致。
1. 理解多合并基的影响
你遇到的是多合并基场景:git merge-base --all返回了两个提交,其中b8d0b8b6是feature2合并到main的提交,而你虽然把feature2合并到了feature1,但Git的合并逻辑在处理多个基时,会用这些基的"联合"状态来对比分支差异。
2. 找出main中导致冲突的提交
直接用以下命令,找出main中在合并基之后修改setup.cfg的所有提交:
git log --oneline 217f353..main -- setup.cfg
或者更准确地,针对两个合并基,找出main中不在feature1里的提交:
git log --oneline feature1..main -- setup.cfg
这个命令会列出main分支上有,但feature1分支没有的setup.cfg修改提交,其中就包含导致冲突的b8d0b8b6(feature2合并到main的提交)。
3. 为何git log --merge只显示一个提交?
因为git log --merge默认只显示在合并基之后修改冲突文件,且只在其中一个分支存在的提交。而b8d0b8b6对应的修改,你已经通过合并feature2到feature1的操作,让feature1也包含了这个修改的"解决版本",但Git的合并逻辑认为main中的版本和feature1中的版本仍存在差异,所以冲突产生,但git log --merge没把main侧的提交列出来。
4. 彻底解决冲突的建议
既然你已经在feature1中合并过feature2并解决了冲突,现在可以用git rebase把feature1重新基于main最新提交,这样能更清晰地处理冲突:
git checkout feature1 git rebase main
在rebase过程中处理setup.cfg的冲突,完成后再合并到main即可。
内容的提问来源于stack exchange,提问作者Florian Brucker

