git diff 在文件相同时报告差异

标签 git git-diff

我正在尝试将一些更改从我的存储库中的一个分支手动 merge 到另一个分支。我使用以下方法找出差异:

git diff branchA...branchB path/to/files > diff.patch

效果很好,显示了我的所有更改。然后我去手动更新了我想要的 branchA 中的文件并提交了它们。 Git status 显示一切都是最新的。现在我想再次运行差异以确保我没有遗漏任何东西。

但是,当我运行 diff 时,它显示了与我第一次运行时相同的所有差异。例如,它向我显示了在 branchB 中添加的行,即使确切的行现在存在于 branchA 中。

我猜这是因为我手动进行了 merge ,但我现在如何再次获得正确的差异?

最佳答案

三点语法 ( branchA...branchB ) 在 git diff 中有特殊含义这与大多数 1 git 命令中的正常含义不同。

通常,X...Y告诉git rev-list构造两个集合的对称差异:第一个集合是所有可从X 到达的提交的集合,第二个是可从 Y 到达的所有提交的集合.对称差异是“所有提交都可以从 either X or Y 到达,但不能同时从两者到达”。换句话说,如果追溯 X 的历史和 Y最终到达一些公共(public)提交(这些提交是最低公共(public)祖先)然后我们只剩下既不是 LCA 也不是祖先的提交。

LCA 也就是我们所说的 merge 基地。在大多数情况下,只有一个 LCA,它是您确定的两个提交的(单一) merge 基础。当这两个提交是两个不同分支的提示时,这很有意义,对称的差异是“在 merge 基础之后,在两个分支上提交”,这是像 cherry-picking 这样的操作的一个很好的起点。

git diff 没多大用处| , 尽管。原因是 git diff比较两个而且只有两个提交。2如果你给它一大堆很多提交,它不知道该做什么。

因为 git diff仅适用于一对提交,它重新定义了双点 X..Y和三点 X...Y语法。对于双点版本,它只接受两个命名的提交,但对于三点版本,它做了一些聪明的事情:

git diff X...Y 表示 git diff $(merge-base X Y) Y

由于三点语法通常在(通常是单个) merge 基处停止,git diff假设你在给它这个语法时一定打算做一些类似 merge 的事情。因此,它会为您命名的提交找到一个 merge 基础。运气好的话,只有一个最低公共(public)祖先,所以这是 merge 基础。然后它将 merge 基础提交与两个命名提交中的第二个进行比较。

如果这两个名称是分支名称(在本例中),并且您 checkout 第一个 分支并向其添加一个或多个提交(在本例中) ,我们可以确定两个分支提示的 merge 基础是不变的。 第二个 分支也没有改变(因为我们只修改了第一个分支,向它添加了新的提交)。因此,如果我们现在运行一个新的 git diff使用相同的三点语法,我们将比较完全相同的两个提交

要亲自查看,请使用:

git merge-base branchA branchB

并记下打印的提交 ID,然后查看 branchA并添加一个提交并运行相同的 git merge-base命令。您可能还想运行 git rev-parse branchAgit rev-parse branchB添加新提交之前和之后:你会看到 branchAbranchB 时获取新的提交没有。

您还可以运行:

git rev-list --left-right branchA...branchB

这将生成对称差异提交列表(不包括 merge 基),用 < 标记它们和 >字符以显示两个(左侧或右侧)祖先中的哪一个选择了它们。 (将 rev-list 更改为 log --graph 以查看日志消息。)


1任何使用 git rev-list 的 git 命令, 反正。这包括 git log (事实上​​,git loggit rev-list 本质上是相同的命令,具有不同的默认输出)。

2好吧,git 也为 merge 提交做了它所谓的“组合差异”,但你不能从 git diff 中得到一个。本身。

关于git diff 在文件相同时报告差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35028333/

相关文章:

Git:对新分支的更改反射(reflect)在 master 上,直到第一次提交

git - 有没有从点或分支原点到 "git diff"的快速方法?

windows - Git diff 在子模块中不起作用

git - Jenkins的Gradle发布插件未推送发布版本

git - 如果 --abort 不起作用,如何中止交互式 rebase ?

git - 两台笔记本电脑如何在没有互联网的情况下相互推/pull

git - GIT的缩写是什么?

git - 黑白 'git diff HEAD' 和 'git diff HEAD HEAD~1' 有什么区别?

git - 需要修补的子模块的 git 解决方案是什么?

git - 从 Git 中的多个提交中导出修改后的文件