我将 git show 和 git log 与相同的选项进行比较。我在不同的提交上得到不同的结果。我还没有真正深入研究文档来弄清楚这是为什么,但我猜测这与每个命令如何解释修订列表以及提交图的样子有关?例如,FFmpeg 上的演示:
案例1 git日志:
> git log -n1 --numstat --format='%H' 00049f193d07cec0409069bc51d0dcb8ab9da837
00049f193d07cec0409069bc51d0dcb8ab9da837
Run Code Online (Sandbox Code Playgroud)
案例1 git显示:
> git show -n1 --numstat --format='%H' 00049f193d07cec0409069bc51d0dcb8ab9da837
00049f193d07cec0409069bc51d0dcb8ab9da837
4 0 libavcodec/mpegaudiodecheader.c
Run Code Online (Sandbox Code Playgroud)
案例2 git日志:
> 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
Run Code Online (Sandbox Code Playgroud)
案例2 git显示:
> 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
Run Code Online (Sandbox Code Playgroud)
基本上,我很困惑为什么对于情况 1,log 省略了更改的文件 ( libavcodec/mpegaudiodecheader.c),而 show 包含它们,然后在情况 2 中,输出是相同的。
以供参考:
> git diff --numstat 00049f193d07cec0409069bc51d0dcb8ab9da837 00049f193d07cec0409069bc51d0dcb8ab9da837^
0 4 libavcodec/mpegaudiodecheader.c
Run Code Online (Sandbox Code Playgroud)
Joseph K. Strauss的答案是正确的(这是合并提交),但并不完整。缺失的信息分散在 Git 文档和源代码中,这就是为什么它们很难找到。
首先,00049f193d07cec0409069bc51d0dcb8ab9da837 确实是合并提交。它的两个父母是d832020bd853f84b96a3fdf3e0a385d8492ec8c8和fcbcc561e0fdc95a7dd48b92db53846726aec27e(我们不需要知道它们的确切数字,但不妨记录它们以显示其“合并性”)。
文档给git show了我们一个提示:
任何差异生成命令都可以使用
-c或选项在显示合并时--cc生成组合差异。这是显示与git-diff(1)或git-show(1)合并时的默认格式。另请注意,您可以-m为这些命令中的任何一个提供选项,以强制与合并的各个父级生成差异。
这里缺少的是-c和本身的描述--cc,在两个链接的手册页中都找不到它,但在git diff-tree. 然而,在我们开始之前,值得先查看文档git diff,我们在其中找到了以下内容:
“git-diff-tree”、“git-diff-files”和“git-diff --raw”可以采用
-c或--cc选择为合并提交生成 diff 输出。[截图示例]
请注意,组合差异仅列出所有父级修改的文件。
(我的粗体字,但这确实非常重要;我们稍后会再次看到它,我将再次使用粗体)。现在我们可以跳回到,在那里我们找到和 的git diff-tree实际描述:-c--cc
-c
此标志更改合并提交的显示方式(这意味着仅当命令给出一棵树状或时它才有用--stdin)。它同时显示每个父项与合并结果的差异,而不是一次显示父项与结果之间的成对差异(这就是该选项的-m作用)。此外,它仅列出所有父级修改的文件。
--cc
此标志更改合并提交补丁的显示方式,与该-c选项类似。它暗示了-c和-p选项,并通过省略无趣的块来进一步压缩补丁输出,这些块的父项中的内容只有两个变体,并且合并结果选择其中之一而不进行修改。当所有块都无趣时,不会显示提交本身和提交日志消息,就像任何其他“空差异”情况一样。
请注意,这告诉我们这--cc是默认值,git show但没有提及git log。事实证明,git log默认情况下只是完全抑制合并差异输出,而git showset --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]
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
这是组合差异选项(如果选择)可以显示合并的地方。同时,对于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;
}
Run Code Online (Sandbox Code Playgroud)
因此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
Run Code Online (Sandbox Code Playgroud)
如果我们简单地添加-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
Run Code Online (Sandbox Code Playgroud)
现在稍微思考一下就可以清楚为什么我们只看到一个文件:它是唯一一个来自父母双方都进行了更改的文件。 这与任何组合差异具有相同的约束,并且果然,替换--cc为-c(使用相同的git log)会产生相同的结果。
如果没有-m、-c、 或--cc,git log则打印合并的日志消息,但从不尝试显示合并提交与其父项的差异。如果没有任何这些选项,则git show设置--cc. 这大约有一半记录在案。
| 归档时间: |
|
| 查看次数: |
2931 次 |
| 最近记录: |