我在git存储库中有一个提交,其中git show
表示只修改了一个文件,而git diff
显示两个文件被修改。
我创建了一个展示相同行为的简单示例存储库。
在样本回购中,我们有这个简单的历史记录:
* c248261 (HEAD, origin/master, master) Merged feature into master.
|\
| * d23c497 (feature) Modified fileA and fileB in feature.
* | 06a7f5e Modified fileA and fileC in master.
* | 9cd1a6e Merged feature into master.
|\ \
| |/
| * aed2e5e Modified fileA and fileB in feature.
* | c6e4fe7 Mofified fileC in master.
* | 19ed298 Merged feature to master.
|\ \
| |/
| * c0f2abc Added fileB and modified fileA in feature.
* | 47c67cf Added fileC in master.
|/
* 56a9b73 Added fileA in master.
当我查看提交c248261时,例如SourceTree,我可以看到fileA
和fileB
已被修改。使用git diff
会得到相同的结果:
$ git diff --name-only c248261^..c248261
fileA
fileB
$
或使用速记符号:
$ git diff --name-only c248261^!
fileA
fileB
$
当我尝试使用git show
获取相同信息时,只显示两个文件中的一个:
$ git show --name-only c248261
commit c2482616b6b6781d0580ec1008ef7d0ab5f73a70
Merge: 06a7f5e d23c497
Author: ...
Date: Fri Aug 15 16:19:02 2014 +0200
Merged feature into master.
fileA
$
同样,git diff-tree
没有显示任何内容:
$ git diff-tree c248261
$
有人可以解释这个区别吗?
我正在使用git版本2.0.4。
答案 0 :(得分:2)
git show
?命令git show
是一个通用命令,用于在git
中显示有关对象的信息。
从手册页(git help show
):
Shows one or more objects (blobs, trees, tags and commits).
...
For commits it shows the log message and textual diff.
It also presents the merge commit in a special format as produced by
git diff-tree --cc
...
因此,git show
的输出不同,因为这是 merge 提交而不是 plain 提交。
git diff-tree --cc
的手册页说:
--cc
This flag changes the way a merge commit patch is displayed, in a
similar way to the -c option. It implies the -c and -p options and
further compresses the patch output by omitting uninteresting hunks whose
the contents in the parents have only two variants and the merge result
picks one of them without modification. When all hunks are uninteresting,
the commit itself and the commit log message is not shown, just like in
any other "empty diff" case.
进一步
-c
This flag changes the way a merge commit is displayed (which means
it is useful only when the command is given one <tree-ish>, or
--stdin). It shows the differences from each of the parents to the
merge result simultaneously instead of showing pairwise diff
between a parent and the result one at a time (which is what the -m
option does). Furthermore, it lists only files which were modified
from all parents.
请注意我在此重复的最后一行:
Furthermore, it lists only files which were modified from all parents.
因此,合并提交中的git show
将仅列出在将提交与所有父项合并进行比较时修改的文件。对于普通合并(即2个父母),这正是合并的文件。例如,如果您执行此合并:
git checkout master
git merge feature
git show
列出的文件是合并前在 master
和feature
中修改的文件,并在合并提交中合并在一起
对于章鱼合并 - 即两个以上的父母 - 生成的文件必须与所有父母中的文件不同,才能由git show
显示。
请注意,在合并提交中使用git show
时,其他文件也会显示。例如,如果您调用git merge --no-commit
然后在提交之前执行以下任何操作,则git show
上的这些文件也将显示在合并提交中:
git show
正在做的是显示所谓的组合差异。
在合并提交上运行命令git show
的结果可以被认为是仅显示已合并的文件,而不是仅显示从两个父项之一中保持不变的文件。
这有点令人惊讶,因为许多人希望看到哪些文件与您刚刚合并的分支相比被修改了。
那么如果你想看看父母之间的差异怎么办?
让我们最后看一下git show
的手册页:
COMBINED DIFF FORMAT
Any diff-generating command can take the `-c` or --cc option to produce
a combined diff when showing a merge. This is the default format when
showing merges with git-diff(1) or git-show(1). Note also that you can
give the `-m' option to any of these commands to force generation of
diffs with individual parents of a merge.
因此我们可以使用-m
选项来获取这两个差异:
git show -m commit
这将逐一为你提供所有父母的差异。
要查看合并提交与您合并到的分支上的上一次提交(即第一个父级)之间的区别,请使用以下任一命令:
git show --first-parent commit
git diff commit^..commit
git diff commit^!
--first-parent
选项确实属于git log
,但也适用于git show
。表示法commit^!
是commit^..commit
的简写。
要查看合并提交与您合并的分支之间的区别(例如,查看您从其他分支中遗漏的内容),请使用
git diff commit^2..commit
符号commit^2
表示commit
的第二个父级。
如果您有超过2个父母(即章鱼合并),我相信您可以猜测如何区分第3,第4等提交。
答案 1 :(得分:0)
通过查看提交c248261
的提交消息,可能提交您正在寻找的是合并提交。合并提交有多个父母。
修订参数的后缀^表示该提交对象的第一个父级。
所以,当你说,
$ git diff --name-only c248261^..c248261
fileA
fileB
$
它从提交c248261
的第一个父项执行差异。
你可以试试,
$ git diff --name-only c248261^2..c248261
将为您提供以下结果,
fileA
--other files if exist--
在两个父母合并之后,会创建一个新的提交,即c248261
,它只有一个差异文件,这就是你所说的,
git show --name-only c248261
答案 2 :(得分:0)
从手册页(git help show
)
For commits it shows the log message and textual diff.
It also presents the merge commit in a special format as produced by
git diff-tree --cc
...
For plain blobs, it shows the plain contents.
因此,git show
的输出不同,因为这是合并提交而不是普通blob。 git diff-tree --cc
的文档说:
--cc
This flag changes the way a merge commit patch is displayed, in a
similar way to the -c option. It implies the -c and -p options and
further compresses the patch output by omitting uninteresting hunks whose
the contents in the parents have only two variants and the merge result
picks one of them without modification. When all hunks are uninteresting,
the commit itself and the commit log message is not shown, just like in
any other "empty diff" case.