简体   繁体   English

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

[英]git merge conflicts: which commit was the common ancestor?

I want to know the identity of the "common ancestor" commit during a git merge conflict resolution.我想知道 git 合并冲突解决期间“共同祖先”提交的身份。

Said differently: I want to know the hash of the revision that the BASE version is being drawn from when I'm resolving conflicts during a git merge .换句话说:当我在git merge期间解决冲突时,我想知道BASE 版本的修订版本hash。

Hopefully, there is a command that will tell me this information?希望有一个命令可以告诉我这些信息?

Why I want to know为什么我想知道

  • I am (unfortunately) doing a very complicated merge, with lots of conflicts.我(不幸的是)正在做一个非常复杂的合并,有很多冲突。
  • I want to be able to visualize the two change paths ( BASE -> LOCAL and BASE -> REMOTE ) to give me more context about how these two sets of changes happened, who made them, when, on what branches, etc...我希望能够可视化这两个更改路径( BASE -> LOCALBASE -> REMOTE ),以便为我提供更多有关这两组更改如何发生、谁在何时、在哪些分支上进行更改等的上下文...

Helpful (?) related info有用的(?)相关信息

  • Recall that for any particular conflicting file, there is回想一下,对于任何特定的冲突文件,有

    • a BASE version ( git show:1:<path> ), which comes from the common ancestor commit (whose identity is the answer to my question)一个 BASE 版本( git show:1:<path> ),它来自共同的祖先提交(其身份是我问题的答案)
    • the LOCAL (branch I was on: git show:2:<path> ) version and LOCAL(我所在的分支: git show:2:<path> )版本和
    • the REMOTE (branch I'm merging in: git show:3:<path> ) version REMOTE(我正在合并的分支: git show:3:<path> )版本
  • I know that I can get the SHA hash of the BASE file itself, by using git ls-files -u , which gives output like我知道我可以通过使用git ls-files -u获得 BASE 文件本身的 SHA hash,它给出 output

$ git ls-files -u | grep "<path>"
100644 <SHA of BASE file> 1 <path>
100644 <SHA of LOCAL file> 2 <path>
100644 <SHA of REMOTE file> 3 <path>
  • I am using git mergetool and gvimdiff3 to view conflicts.我正在使用git mergetoolgvimdiff3来查看冲突。 This tool shows each conflicting file (with the "<<<" , ">>>" , "|||" conflict markers, as well as three other files for reference: LOCAL, BASE, and REMOTE. All very well and good.此工具显示每个冲突文件(带有"<<<"">>>""|||"冲突标记,以及其他三个文件供参考:LOCAL、BASE 和 REMOTE。一切都很好.

  • My BASE files sometimes have conflict markers in them (:) which look like this:我的 BASE 文件中有时会有冲突标记 (:),如下所示:

<<<<<<<<< Temporary merge branch 1
<snip>
||||||||| merged common ancestors
=========
<snip>
>>>>>>>>> Temporary merge branch 2

When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge.

  • I guess what I am seeing is that the "common ancestor" is a merged hybrid of several commits.我想我所看到的是“共同祖先”是几个提交的合并混合体。 Nevertheless, that merged hybrid must have been generated somehow, must have a SHA, and must have parents whose identities I want to know.尽管如此,那个合并后的混合体一定是以某种方式生成的,必须有一个 SHA,并且必须有我想知道其身份的父母。

This one is tricky, and a bit nasty.这个很棘手,有点讨厌。 You're completely correct here:你在这里完全正确:

I guess what I am seeing is that the "common ancestor" is a merged hybrid of several commits.我想我所看到的是“共同祖先”是几个提交的合并混合体。 Nevertheless, that merged hybrid must have been generated somehow, must have a SHA, and must have parents whose identities I want to know.尽管如此,那个合并后的混合体一定是以某种方式生成的,必须有一个 SHA,并且必须有我想知道其身份的父母。

As LeGEC said , you do have both HEAD and MERGE_HEAD available when Git stops with this merge conflict.正如LeGEC 所说,当 Git 因合并冲突而停止时,您确实可以使用HEADMERGE_HEAD

You can find the hash IDs of the merge bases (plural) with:您可以通过以下方式找到合并基础(复数)的 hash ID:

git merge-base --all HEAD MERGE_HEAD

Since you are using merge-recursive, what Git did was:由于您使用的是合并递归,因此 Git 所做的是:

  • Select two of the merge bases. Select 两个合并基地。
  • Run git merge-recursive on them.对它们运行git merge-recursive (This may itself find more than two merge bases; if so, see this procedure.) (这本身可能会找到两个以上的合并基础;如果是这样,请参阅此过程。)
  • Commit the result.提交结果。 This is now the merge-base-so-far.这是目前为止的合并基础。 (This commit has a hash ID.) (此提交的 ID 为 hash。)
  • Pick the next of the merge bases, if there are more than two bases, and merge that with the merge-base-so-far;选择下一个合并基础,如果有两个以上的基础,并将其与 merge-base-so-far 合并; this is now the new merge-base-so-far.这是目前新的合并基础。
  • Repeat until all merge bases are used up.重复直到所有合并基地都用完。

The final output of this process is a commit hash ID.这个过程最后的 output 是一个 commit hash ID。 This hash ID is not saved or shown anywhere.这个 hash ID 不会在任何地方保存或显示。 You can get all the inputs to this process from git merge-base --all of course.您可以从git merge-base --all获取此过程的所有输入——当然。

Normally, when a merge has conflicts, Git stops and makes you fix them.通常,当合并发生冲突时,Git 会停止并让您修复它们。 But when merging merge bases produces conflicts, Git just goes ahead and commits the conflicted merge bases.但是当合并合并基产生冲突时,Git 继续并提交冲突的合并基。 This is... not good.不是很好。 (I'm not claiming it's bad here, just that it's not good: it gets very messy. The new merge-ort does not do this, I think, but I have yet to digest precisely what it does do.) These conflict markers are indeed what you are seeing. (我在这里并不是说它不好,只是说它不好:它变得非常混乱。我认为新的 merge-ort 不会这样做,但我还没有准确地消化它所做的事情。)这些冲突标记确实是你所看到的。

The tools Git has here are not quite up to the job, but using git merge-base --all , you can at least inspect each of the inputs. Git 此处提供的工具不太适合这项工作,但使用git merge-base --all ,您至少可以检查每个输入。

If you are in a conflict triggered by a git merge (eg: not a cherry-pick or a rebase ):如果您处于由git merge触发的冲突中(例如:不是cherry-pickrebase ):

  • your current commit is still HEAD你当前的提交仍然是HEAD
  • the merged commit is stored in a special ref .git/MERGE_HEAD合并的提交存储在一个特殊的 ref .git/MERGE_HEAD

So you can get:所以你可以得到:

  • your current commit ("mine"): git rev-parse HEAD您当前的提交(“我的”): git rev-parse HEAD
  • the other commit ("theirs"): git rev-parse MERGE_HEAD另一个提交(“他们的”): git rev-parse MERGE_HEAD
  • the base commit: git merge-base MERGE_HEAD HEAD基础提交: git merge-base MERGE_HEAD HEAD

You can actually use HEAD and MERGE_HEAD as valid names to point at these commits, so:您实际上可以使用HEADMERGE_HEAD作为有效名称来指向这些提交,因此:

  • git diff HEAD...MERGE_HEAD or git difftool -d HEAD...MERGE_HEAD will show you the changes introduced by "them" since the fork point, git diff HEAD...MERGE_HEADgit difftool -d HEAD...MERGE_HEAD将显示自分叉点以来“他们”引入的更改,
  • git diff MERGE_HEAD...HEAD or git difftool -d MERGE_HEAD...HEAD will show you the changes introduced in "me" since the fork point. git diff MERGE_HEAD...HEADgit difftool -d MERGE_HEAD...HEAD将显示自分叉点以来“me”中引入的更改。

a note about the three dots notation git diff A...B , quoting the docs :关于三点符号git diff A...B的注释,引用文档

git diff A...B is equivalent to git diff $(git merge-base AB) B git diff A...B相当于git diff $(git merge-base AB) B


To solve conflicts for individual files:要解决单个文件的冲突:

  • kdiff3 in 3 way merge defaults to showing 4 panes, which allows you to view on the same screen: kdiff3 in 3 way merge 默认显示 4 个窗格,这允许您在同一屏幕上查看:
    • the diff between LOCAL and BASE LOCALBASE的区别
    • the diff between BASE and REMOTE BASEREMOTE的区别
    • the result of what you are about to save on the bottom pane您要保存在底部窗格中的结果

I'm not familiar with vimdiff , but there surely is a way to either have this 4-panes view, or commands to toggle between the 3 way merge and either of the two diffs.我不熟悉vimdiff ,但肯定有一种方法可以拥有这个 4 窗格视图,或者可以在 3 路合并和两个差异中的任何一个之间切换的命令。

  • I use meld as a graphical diff viewer, and I know this one has:我使用meld作为图形差异查看器,我知道这个有:
    • a --auto-merge flag, which, in 3 way merge view, automatically combines non conflicting diff chunks,一个--auto-merge标志,在 3 路合并视图中,自动合并不冲突的 diff 块,
    • a way to open several diff views from the command line, so I open LOCAL BASE and BASE REMOTE diffs in separate tabs一种从命令行打开多个差异视图的方法,所以我在单独的选项卡中打开LOCAL BASEBASE REMOTE差异

Here are the configuration settings I added to my gitconfig:这是我添加到我的 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

I'm pretty sure other diff viewers such as vimdiff3 or kdiff3 have an equivalent --auto-merge option, but I will let you scan the documentation to find out how it's named and how to use it.我很确定其他差异查看器(例如vimdiff3kdiff3 )具有等效的--auto-merge选项,但我会让您扫描文档以了解它的命名方式和使用方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM