Git合并冲突:哪个提交是共同祖先?

5
我想知道在Git合并冲突解决期间 "共同祖先" 提交的身份。换句话说,我想知道当我在解决 `git merge` 冲突时,基础版本正在从哪个修订版中获取。希望有一个命令可以告诉我这个信息?为什么我要知道:我正在进行非常复杂的合并,并且存在许多冲突。我想能够可视化两个更改路径 (`BASE -> LOCAL` 和 `BASE -> REMOTE`),以便更多地了解这两组更改是如何发生的、谁进行了更改、何时进行了更改、在哪些分支上进行了更改等等... 有用的相关信息:请记住,对于任何特定的冲突文件,都有一个 BASE 版本 (`git show :1:
2个回答

3

这个有点棘手,也有点讨厌。你在这里完全正确:

我想我看到的是,“共同祖先”是几个提交的混合合并。不过,那个混合合并肯定是以某种方式生成的,必须有一个SHA,并且必须有父级其身份我想知道。

就像LeGEC所说的那样,当Git停止此合并冲突时,您确实同时拥有HEADMERGE_HEAD

您可以使用以下命令找到合并基础(复数)的哈希ID:

git merge-base --all HEAD MERGE_HEAD

由于您正在使用merge-recursive,Git所做的是:
- 选择两个合并基础。 - 在它们上运行git merge-recursive。(这本身可能会发现多个合并基础;如果是这样,请参见此过程。) - 提交结果。这是当前的合并基地。(此提交具有哈希ID。) - 如果有多个合并基,则选择下一个合并基,并将其与当前的合并基地合并;这是新的合并基地。 - 重复直到使用完所有合并基。
此过程的最终输出是一个提交哈希ID。 这个哈希ID没有被保存或显示在任何地方。当然,您可以从git merge-base --all获取此过程的所有输入。
通常,当合并存在冲突时,Git会停止并要求您解决它们。但是当合并合并基产生冲突时,Git会继续并提交冲突的合并基。这不好。(我不是在这里声称它是糟糕的,只是说它不好:它变得非常混乱。我认为新的合并ort不会这样做,但我还需要仔细分析它确切做了什么。)这些冲突标记就是您看到的。Git在这里使用的工具并不完全胜任,但是使用git merge-base --all,您至少可以检查每个输入。

啊,git merge-base --all:这就是我要找的。不过,出于好奇,最终合并提交是否仍然存在于存储库中?我不能像查找其他未链接/丢失提交一样找到它吗? - stochastic
1
确实在存储库中(直到 git gc 清除它)。最近的某些版本的 git fsck 存在一些错误,无法找到悬空的提交和 blob(请参见此处)。 - torek

2
如果您遇到由 git merge 引发的冲突(例如:不是 cherry-pick 或者 rebase),则:
  • 您当前的提交仍然是 HEAD
  • 合并的提交存储在特殊引用 .git/MERGE_HEAD
因此,您可以获得以下内容:
  • 您当前的提交("mine"):git rev-parse HEAD
  • 另一个提交("theirs"):git rev-parse MERGE_HEAD
  • 基础提交:git merge-base MERGE_HEAD HEAD

您可以使用HEADMERGE_HEAD作为有效名称指向这些提交,因此:
  • git diff HEAD...MERGE_HEADgit difftool -d HEAD...MERGE_HEAD将显示自分叉点以来“them”引入的更改,
  • git diff MERGE_HEAD...HEADgit difftool -d MERGE_HEAD...HEAD将显示自分叉点以来“me”引入的更改。
关于三个点符号git diff A...B的注释,引用文档

git diff A...B等同于git diff $(git merge-base A B) B


解决单个文件的冲突:
  • kdiff3 在三方合并中默认显示四个面板,这使您可以在同一屏幕上查看:
    • LOCALBASE 之间的差异
    • BASEREMOTE 之间的差异
    • 您即将保存的结果在底部窗格中

我不熟悉 vimdiff,但肯定有一种方法可以拥有这个四面板视图,或者切换到三方合并和两个差异之间的命令。

  • 我使用 meld 作为图形化差异查看器,我知道它有:
    • --auto-merge 标志,在三方合并视图中自动组合非冲突的差异块,
    • 一种从命令行打开多个差异视图的方式,因此我在单独的选项卡中打开 LOCAL BASEBASE REMOTE 差异

这是我添加到 gitconfig 的配置设置:

git config --global mergetool.meld3.cmd \
    'meld --auto-merge $LOCAL $BASE $REMOTE -o $MERGED'\
    ' --diff $LOCAL $BASE --diff $BASE $REMOTE'

git config --global merge.tool meld3

我相信其他的差异查看器,如vimdiff3kdiff3也有类似的--auto-merge选项,但是我会让你扫描文档以找出它的名称和使用方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接