我试图将一些分支中的一些更改合并到我的存储库中的另一个分支中。我使用以下内容来找出差异:
git diff branchA...branchB path/to/files > diff.patch
这很有效,并展示了我所有的变化。然后我去手动更新了我想要的branchA中的文件并提交了它们。 Git状态显示一切都是最新的。现在我想再次运行差异,以确保我没有错过任何东西。
然而,当我运行diff时,它显示了与第一次运行它时相同的差异。例如,它显示我在branchB中添加的行,即使branchA中现在存在确切的行。
我猜它是因为我手动完成合并,但我现在又如何获得正确的差异呢?
答案 0 :(得分:5)
三点语法(branchA...branchB
)在git diff
中具有特殊含义,与大多数 1 git命令中的正常含义不同。
通常,X...Y
告诉git rev-list
构建两个集合的对称差异:第一个是从X
可以访问的所有提交的集合,以及第二个是从Y
可到达的所有提交的集合。对称差异是"所有提交都可以从 X
或 Y
到达,但不能同时来自"。换句话说,如果追溯X
和Y
的历史记录最终到达某些共同提交 - 这些提交是最低共同的祖先 - 那么我们只留下提交既不是LCA也不是祖先。
LCA就是我们所说的合并基础。在大多数情况下,只有一个LCA,它是您识别的两个提交的(单数)合并基础。当这两个提交是两个不同分支的提示时,这很有意义,并且对称差异是"在合并基础之后提交,在两个分支上#34;这是像这样的操作的一个很好的起点摘樱桃。
但是,对于git diff
来说,它并不是很好。原因是git diff
比较两个而且只有两个提交。 2 如果你给它一大堆提交,它就不知道该怎么做。
由于git diff
仅适用于一对提交,因此它重新定义了两点X..Y
和三点X...Y
语法。对于双点版本,它只需要两个命名提交,但对于三点版本,它做了一些聪明的事情:
git diff X...Y
表示 git diff $(merge-base X Y) Y
由于三点语法通常在(通常是单个)合并基础上停止,git diff
假设您必须打算在给出这种语法时执行merge-ish。因此,它为您命名的提交找到合并基础。运气好的话,只有一个最低共同祖先,所以这是 合并基础。然后,它将合并基础提交与两个命名提交中的第二个进行比较。
如果这两个名称是分支名称(在这种情况下是这样),并且您检查第一个分支并向其添加一个或多个提交(就像在这种情况下那样) ,我们可以肯定两个分支的合并基础没有变化。 第二个分支也保持不变(因为我们只修改了第一个,为它添加了新的提交)。因此,如果我们现在使用相同的三点语法运行新的git diff
,我们将比较完全相同的两个提交。
要亲自查看,请使用:
git merge-base branchA branchB
并记下打印的提交ID,然后签出branchA
并添加提交并运行相同的git merge-base
命令。您可能还希望在添加新提交之前和之后运行git rev-parse branchA
和git rev-parse branchB
:您会看到branchA
获取新提交而branchB
没有。
您还可以运行:
git rev-list --left-right branchA...branchB
将生成对称差异提交列表(不包括合并基础),用<
和>
字符标记它们以显示选择的两个(左侧或右侧)祖先中的哪一个他们。 (将rev-list
更改为log --graph
以查看日志消息。)
1 无论如何,任何使用git rev-list
的git命令。这包括git log
(事实上,git log
和git rev-list
基本上是相同的命令,具有不同的默认输出。)
2 好吧,git也做它所谓的&#34;组合差异&#34;对于合并提交,但您无法从git diff
本身获得一个。