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