我想知道"共同祖先";在git合并冲突解决过程中提交。
换句话说:当我在git merge
期间解决冲突时,我想知道从中提取BASE版本的修订版的哈希。
希望有一个命令能告诉我这些信息?
为什么我想知道
- 我(很不幸)正在进行一个非常复杂的合并,有很多冲突
- 我希望能够可视化这两条变化路径(
BASE -> LOCAL
和BASE -> REMOTE
),为我提供更多关于这两组变化是如何发生的,是谁做出的,何时,在什么分支上,等等的上下文
有用的(?)相关信息
-
回想一下,对于任何特定的冲突文件,都有
- 一个BASE版本(
git show :1:<path>
),它来自公共祖先提交(其身份是我问题的答案) - LOCAL(分支I位于:
git show :2:<path>
)版本,并且 - REMOTE(我正在合并的分支:
git show :3:<path>
)版本
- 一个BASE版本(
-
我知道我可以通过使用
git ls-files -u
来获得BASE文件本身的SHA哈希,它给出了类似的输出
$ 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>
我使用
git mergetool
和gvimdiff3
来查看冲突。此工具显示每个冲突文件(带有"<<<"
、">>>"
、"|||"
冲突标记),以及其他三个可供参考的文件:LOCAL、BASE和REMOTE。一切都很好。我的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.
- 我想我看到的是;共同祖先";是几个提交的合并混合体。尽管如此,合并后的混血儿一定是以某种方式产生的,一定有SHA,而且一定有我想知道身份的父母
这个很棘手,而且有点讨厌。你在这里完全正确:
我想我看到的是;共同祖先";是几个提交的合并混合体。尽管如此,合并后的混血儿一定是以某种方式产生的,一定有SHA,而且一定有我想知道身份的父母。
正如LeGEC所说,当Git因合并冲突而停止时,HEAD
和MERGE_HEAD
都可用。
您可以使用找到合并基的哈希ID(复数)
git merge-base --all HEAD MERGE_HEAD
由于您使用的是合并递归,Git所做的是:
- 选择两个合并基
- 对它们运行
git merge-recursive
。(这本身可能会找到两个以上的合并基;如果是,请参阅此过程。) - 提交结果。到目前为止,这是合并的基础。(此提交具有哈希ID。)
- 如果有两个以上的合并基,则拾取下一个合并基,并将其与迄今为止的合并基合并;到目前为止,这是新的合并基础
- 重复此步骤,直到所有合并基数都用完为止
此过程的最终输出是提交哈希ID。此哈希ID不会保存或显示在任何位置当然,您可以从git merge-base --all
获得该过程的所有输入。
通常,当合并发生冲突时,Git会停止并让您修复它们。但是,当合并合并基产生冲突时,Git只是继续并提交冲突的合并基。这是。。。不好。(我并不是说这里的很糟糕,只是不好:变得非常混乱。我认为新的合并端口没有做到这一点,但我还没有确切地理解它的作用。)这些冲突标记确实是你所看到的。
Git在这里拥有的工具并不能完全胜任这项工作,但使用git merge-base --all
,您至少可以检查每个输入。
如果您处于由git merge
触发的冲突中(例如:不是cherry-pick
或rebase
):
- 您当前的提交仍然是
HEAD
- 合并后的提交存储在特殊引用
.git/MERGE_HEAD
中
所以你可以得到:
- 您当前的提交("我的"):
git rev-parse HEAD
- 另一个提交("他们的"):
git rev-parse MERGE_HEAD
- 基本提交:
git merge-base MERGE_HEAD HEAD
您实际上可以使用HEAD
和MERGE_HEAD
作为有效名称来指向这些提交,因此:
- CCD_ 29或CCD_;他们";由于分叉点
- CCD_ 31或CCD_;我"从分叉点开始
关于三点符号git diff A...B
的注释,引用文档:
git diff A...B
等效于git diff $(git merge-base A B) B
要解决单个文件的冲突:
kdiff3
在3路合并中默认显示4个窗格,允许您在同一屏幕上查看:LOCAL
与BASE
的差异- CCD_ 39与CCD_
- 将要保存在底部窗格中的结果
我不熟悉vimdiff
,但肯定有一种方法可以使用这个4窗格视图,也可以使用命令在3向合并和两个diff中的任何一个之间切换。
- 我使用
meld
作为图形差异查看器,我知道这个查看器具有:- 一个
--auto-merge
标志,它在3向合并视图中自动组合不冲突的diff块 - 一种从命令行打开几个diff视图的方法,因此我在单独的选项卡中打开
LOCAL BASE
和BASE REMOTE
diff
- 一个
以下是我添加到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
我很确定其他diff查看器,如vimdiff3
或kdiff3
,也有等效的--auto-merge
选项,但我会让您扫描文档,了解它的名称和使用方法。