[英]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为什么我想知道
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 -> LOCAL
和BASE -> REMOTE
),以便为我提供更多有关这两组更改如何发生、谁在何时、在哪些分支上进行更改等的上下文... Helpful (?) related info有用的(?)相关信息
Recall that for any particular conflicting file, there is回想一下,对于任何特定的冲突文件,有
git show:1:<path>
), which comes from the common ancestor commit (whose identity is the answer to my question)git show:1:<path>
),它来自共同的祖先提交(其身份是我问题的答案)git show:2:<path>
) version and git show:2:<path>
)版本和git show:3:<path>
) version 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 mergetool
和gvimdiff3
来查看冲突。 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.
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 因合并冲突而停止时,您确实可以使用
HEAD
和MERGE_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 所做的是:
git merge-recursive
on them.git merge-recursive
。 (This may itself find more than two merge bases; if so, see this procedure.) 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-pick
或rebase
):
HEAD
HEAD
.git/MERGE_HEAD
.git/MERGE_HEAD
So you can get:所以你可以得到:
git rev-parse HEAD
git rev-parse HEAD
git rev-parse MERGE_HEAD
git rev-parse MERGE_HEAD
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:您实际上可以使用
HEAD
和MERGE_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_HEAD
或git 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...HEAD
或git 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 togit 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 个窗格,这允许您在同一屏幕上查看:
LOCAL
and BASE
LOCAL
和BASE
的区别BASE
and REMOTE
BASE
和REMOTE
的区别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 路合并和两个差异中的任何一个之间切换的命令。
meld
as a graphical diff viewer, and I know this one has:meld
作为图形差异查看器,我知道这个有:
--auto-merge
flag, which, in 3 way merge view, automatically combines non conflicting diff chunks,--auto-merge
标志,在 3 路合并视图中,自动合并不冲突的 diff 块,LOCAL BASE
and BASE REMOTE
diffs in separate tabsLOCAL BASE
和BASE 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.我很确定其他差异查看器(例如
vimdiff3
或kdiff3
)具有等效的--auto-merge
选项,但我会让您扫描文档以了解它的命名方式和使用方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.