我将git show和git log与相同的选项进行比较。我在不同的提交上得到了不同的结果。我还没有真正挖掘过文档但还没弄清楚为什么会这样,但是我猜它与每个命令如何解释修订列表以及提交图形是什么有关?例如,关于FFmpeg的演示:
案例1 git log:
> git log -n1 --numstat --format='%H' 00049f193d07cec0409069bc51d0dcb8ab9da837
00049f193d07cec0409069bc51d0dcb8ab9da837
案例1 git show:
> git show -n1 --numstat --format='%H' 00049f193d07cec0409069bc51d0dcb8ab9da837
00049f193d07cec0409069bc51d0dcb8ab9da837
4 0 libavcodec/mpegaudiodecheader.c
案例2 git log:
> git log -n1 --numstat --format='%H' 001d668d40b5f87d19271c7d5521368b5187425b
001d668d40b5f87d19271c7d5521368b5187425b
2 5 libavformat/dvenc.c
2 6 libavformat/gxfenc.c
5 0 libavformat/internal.h
2 5 libavformat/movenc.c
2 5 libavformat/mxfenc.c
7 0 libavformat/utils.c
案例2 git show:
> git show -n1 --numstat --format='%H' 001d668d40b5f87d19271c7d5521368b5187425b
001d668d40b5f87d19271c7d5521368b5187425b
2 5 libavformat/dvenc.c
2 6 libavformat/gxfenc.c
5 0 libavformat/internal.h
2 5 libavformat/movenc.c
2 5 libavformat/mxfenc.c
7 0 libavformat/utils.c
基本上,我很困惑为什么对于案例1,日志省略了更改的文件(libavcodec/mpegaudiodecheader.c
),而show包含它们,然后在案例2中,输出是相同的。
供参考:
> git diff --numstat 00049f193d07cec0409069bc51d0dcb8ab9da837 00049f193d07cec0409069bc51d0dcb8ab9da837^
0 4 libavcodec/mpegaudiodecheader.c
答案 0 :(得分:4)
Joseph K. Strauss's answer是正确的(这是合并提交)但不完全。缺少的信息分散在Git文档和源代码中,这就是为什么它们很难找到的原因。
首先,00049f193d07cec0409069bc51d0dcb8ab9da837
really is a merge commit。它的两个父母是d832020bd853f84b96a3fdf3e0a385d8492ec8c8
和fcbcc561e0fdc95a7dd48b92db53846726aec27e
(我们不需要知道它们的确切数字,但也可以记录它们以显示它的“合并”)。
The git show
documentation给了我们一个提示:
任何差异生成命令都可以在显示合并时使用
-c
或--cc
选项生成组合差异。显示与git-diff(1)或git-show(1)的合并时,这是默认格式。另请注意,您可以为这些命令中的任何一个提供-m
选项,以强制使用合并的单个父项生成差异。
这里缺少的是-c
和--cc
本身的说明,这两个链接的手册页中都找不到,但 中的为git diff-tree
。然而,在我们去那里之前,值得前往the git diff
documentation,我们在那里找到:
“git-diff-tree”,“git-diff-files”和“git-diff --raw”可以使用
-c
或--cc
选项为合并提交生成diff输出。 [剪辑示例]
请注意,组合差异仅列出从所有父级修改过的文件。
(粗体我的,但它确实非常重要;我们会在片刻再次看到它,我将再次使用粗体)。现在我们可以跳回git diff-tree
,在那里我们找到-c
和--cc
的实际说明:
-c
此标志更改了合并提交的显示方式(这意味着仅当命令被赋予一个 tree-ish 或--stdin
时才有用)。它同时显示了每个父项与合并结果的差异,而不是一次显示父项和结果之间的成对差异(这是-m
选项的作用)。此外,它列出了仅从所有父母修改的文件。
--cc
此标志以与-c
选项类似的方式更改合并提交修补程序的显示方式。它意味着-c
和-p
选项,并通过省略不感兴趣的帅哥进一步压缩补丁输出,其中父母的内容只有两个变体,合并结果选择其中一个而不进行修改。当所有的人都不感兴趣时,提交本身和提交日志消息不会显示,就像在任何其他“空差异”情况下一样。
请注意,这告诉我们--cc
是git show
的默认值,但对git log
没有任何说明。事实证明git log
默认只是完全抑制合并差异输出,而git show
设置--cc
。前者似乎没有在任何地方记录,但可以在Git源代码中找到builtin/log.c
和revision.c
:
[revision.c]
void init_revisions(struct rev_info *revs, const char *prefix)
{
memset(revs, 0, sizeof(*revs));
revs->abbrev = DEFAULT_ABBREV;
revs->ignore_merges = 1;
revs->simplify_history = 1;
[snip]
这为所有命令设置忽略合并(revs->ignore_merges = 1
)的默认操作;想要处理合并的命令需要清除标志(这也在Documentation/technical/api-revision-walking.txt
中注明)。
git show
和git log
(以及其他几个)都在builtin/log.c
中实现,其中包含以下内容:
static void log_setup_revisions_tweak(struct rev_info *rev,
struct setup_revision_opt *opt)
{
if (DIFF_OPT_TST(&rev->diffopt, DEFAULT_FOLLOW_RENAMES) &&
rev->prune_data.nr == 1)
DIFF_OPT_SET(&rev->diffopt, FOLLOW_RENAMES);
/* Turn --cc/-c into -p --cc/-c when -p was not given */
if (!rev->diffopt.output_format && rev->combine_merges)
rev->diffopt.output_format = DIFF_FORMAT_PATCH;
/* Turn -m on when --cc/-c was given */
if (rev->combine_merges)
rev->ignore_merges = 0;
}
这是组合差异选项(如果选中)启用显示合并的位置。同时,git show
:
static void show_setup_revisions_tweak(struct rev_info *rev,
struct setup_revision_opt *opt)
{
if (rev->ignore_merges) {
/* There was no "-m" on the command line */
rev->ignore_merges = 0;
if (!rev->first_parent_only && !rev->combine_merges) {
/* No "--first-parent", "-c", or "--cc" */
rev->combine_merges = 1;
rev->dense_combined_merges = 1;
}
}
if (!rev->diffopt.output_format)
rev->diffopt.output_format = DIFF_FORMAT_PATCH;
}
因此git show
会检查是否指定了-m
。如果没有,则会在内部启用-m
,然后启用--cc
,除非有三个明确选项中的任何一个:-c
,--cc
和--first-parent
。前两个有意义(不要覆盖用户的设置),但第三个只是奇怪。 (例如,如果我们去做一个组合差异,但只是在一个父ID中被拉出来,也许以后可以避免引起问题。)
仍然不是很明显的是为什么这些不同:
$ git log --no-walk --numstat 00049f193d07cec0409069bc51d0dcb8ab9da837
[snip output: log message, with no diff-stats]
$ git show --numstat 00049f193d07cec0409069bc51d0dcb8ab9da837
[snip log message]
4 0 libavcodec/mpegaudiodecheader.c
如果我们只是将-m
添加到git log
(以便我们清除rev->ignore_merges
标志),我们就会得到针对父母的numstat差异。但是,如果我们添加--cc
,我们会得到与git show
相同的结果:
$ git log -m --cc --no-walk --numstat 00049f193d07cec0409069bc51d0dcb8ab9da837
[snip log message]
4 0 libavcodec/mpegaudiodecheader.c
并且有点想法现在清楚地说明为什么我们只看到一个文件:它是唯一一个来自父母双方都有变化的文件。这是相同的约束对于任何组合差异,当然,将--cc
替换为-c
(使用相同的git log
)会产生相同的结果。
如果没有-m
,-c
或--cc
,git log
会打印合并的日志消息,但甚至不会尝试向其父级显示合并提交的差异。如果没有这些选项,git show
会设置--cc
。这大约有一半记录在案。
答案 1 :(得分:1)
看起来您的第一次提交(00049f193d07cec0409069bc51d0dcb8ab9da837)是合并。因此,它将假设您不关心查看提交的统计信息,但show将显示第一个父项的差异的numstat。
我试图找到这方面的文档,但我不能。