解决合并冲突后,"git diff"究竟显示了什么?如何只看到新的变化?



我将分支A合并到分支B:

git checkout A
git merge B

在文件c.txt中发生冲突。我通过编辑c.txt文件来解决它。现在,在批准git add c.txt的更改之前,我想看看它们。即查看c.txt和分支a之间的差异。怎么做?

如果我简单地使用git diff c.txt,它显示了比我想要的更多的变化。它似乎同时显示了来自分支B和分支A的更改(与它们共同的原始提交相比)。即结果与git add c.txt; git diff --cached c.txt不同。c.txt被标记为冲突时,git diff c.txt究竟显示了什么?

TL;DR:你可能想要git diff HEAD:c.txt c.txt.


虽然文件被标记为&;conflicted&;,但有多个&;higher stage&;文件在Git索引中的条目。事实上,这就是文件首先是冲突的含义:非冲突的文件处于"阶段0"。在Git的索引中,一个冲突的文件有阶段1、阶段2和/或阶段3的条目(通常三个都有)。

当文件处于冲突状态时,git diff对文件执行组合diff

在文件上使用git add会擦除更高阶段的条目,只留下一个阶段零(无冲突)的文件,这就是为什么它不再以这种方式显示。

现在,在使用git add .txt批准更改之前,我希望看到它们。例如,到查看c.txt和分支a之间的差异怎么做呢?

我通常不打扰这个(我只是读取合并的diff,或git add文件,然后可以看到我想要的没有任何花哨的东西-记住,你仍然可以访问文件的其他版本;只有合并基础版本(很难找到),但是您可以这样做。你必须挑选出你想要比较的两个c.txt副本:

  • 其中之一是,你说,在某些提交(branch A)中的副本:这是A:c.txt
  • 另一个副本由您决定:在HEAD提交中有一个,在MERGE_HEAD提交中有一个,在Git的索引中有三个,在工作树中有一个。棘手的部分是命名每一个,但我们可以使用gitrevisions语法。与A:c.txt一样,HEAD:c.txtMERGE_HEAD:c.txt用于选择这些版本;:1:c.txt选择合并基础版本;:2:c.txt选择--ours版本(从HEAD复制,因此应该匹配HEAD:c.txt),:3:c.txt选择--theirs版本(从MERGE_HEAD复制)。

因此,如果你想,例如,看看HEAD:c.txtMERGE_HEAD:c.txt有什么不同,你可以只运行git diff HEAD:c.txt MERGE_HEAD:c.txt(或git diff :2:c.txt :3:c.txt)。

这对你可能最关心的人没有帮助。工作树中的c.txt副本如何编辑以生成合并的文件?幸运的是,我们可以将其命名为文件名c.txt

在某些情况下,该文件名可能类似于分支名称,以欺骗Git。如果是这种情况,请确保您记住--总是告诉Git:在此之后,所有内容都是文件名,或者至少不是选项,也可能不是分支名称。因此,如果文件不是命名为c.txt而是命名为main,并且:

git diff HEAD:main main

做错了,使用:

git diff HEAD:main -- main

(注意HEAD:main不会被误认为是分支名称,--应该放在两者之间)。

关于序反转问题的说明

如果你想比较in-treec.txt和branch-Ac.txt,两者:

git diff c.txt A:c.txt

:

git diff A:c.txt c.txt

工作。这两个参数的顺序决定了哪个文件是"before"或者左边那个,哪个是后面那个;或者右边的一个,它反过来决定哪些行被删除,哪些行被添加。

在大多数情况下,如果您要求的差异是"向后"&;根据表示的顺序,您可以简单地交换参数。但对于:

git diff HEAD:main -- main

有一个问题:你不能交换这些。这里,git diff -R来拯救:-R标志意味着交换边。所以git diff -R HEAD:main -- main做到了:main文件在左边结束,HEAD:main文件在右边结束。