English ▾ 主题 ▾ 最新版本 ▾ git-diff-tree 上次更新于 2.49.0

名称

git-diff-tree - 比较通过两个树对象找到的 blob 的内容和模式

概要

git diff-tree [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
	      [-t] [-r] [-c | --cc] [--combined-all-paths] [--root] [--merge-base]
	      [<common-diff-options>] <tree-ish> [<tree-ish>] [<path>…​]

描述

比较通过两个树对象找到的 blob 的内容和模式。

如果只给出一个 <tree-ish>,则将提交与其父提交进行比较(请参阅下面的 --stdin)。

请注意,git diff-tree 可以使用封装在提交对象中的树。

选项

-p
-u
--patch

生成补丁(请参阅 使用 -p 生成补丁文本)。

-s
--no-patch

禁止来自 diff 机制的所有输出。对于像 git show 这样的默认显示补丁的命令,用于消除它们的输出,或者取消像 --patch--stat 这样在命令行上较早出现的选项的影响。

-U<n>
--unified=<n>

生成带有 <n> 行上下文的 diff,而不是通常的三行。暗示 --patch

--output=<file>

输出到指定文件,而不是 stdout。

--output-indicator-new=<char>
--output-indicator-old=<char>
--output-indicator-context=<char>

指定用于指示生成的补丁中的新行、旧行或上下文行的字符。 通常,它们分别是 +- 和 ' '。

--raw

以原始格式生成 diff。 这是默认设置。

--patch-with-raw

-p --raw 的同义词。

--indent-heuristic

启用启发式算法,该算法会移动 diff hunk 边界,使补丁更易于阅读。 这是默认设置。

--no-indent-heuristic

禁用缩进启发式算法。

--minimal

花费额外的时间来确保生成尽可能小的 diff。

--patience

使用 "patience diff" 算法生成 diff。

--histogram

使用 "histogram diff" 算法生成 diff。

--anchored=<text>

使用 "anchored diff" 算法生成 diff。

可以多次指定此选项。

如果一行同时存在于源和目标中,仅存在一次,并且以 <text> 开头,则此算法会尝试阻止它在输出中显示为删除或添加。 它在内部使用 "patience diff" 算法。

--diff-algorithm=(patience|minimal|histogram|myers)

选择一种 diff 算法。 变体如下

default
myers

基本的贪婪 diff 算法。 目前,这是默认设置。

minimal

花费额外的时间来确保生成尽可能小的 diff。

patience

生成补丁时使用 "patience diff" 算法。

histogram

此算法扩展了 patience 算法以“支持低出现率的常见元素”。

例如,如果您将 diff.algorithm 变量配置为非默认值,并且想要使用默认值,则必须使用 --diff-algorithm=default 选项。

--stat[=<width>[,<name-width>[,<count>]]]

生成 diffstat。 默认情况下,将为文件名部分使用尽可能多的空间,其余部分用于图形部分。 最大宽度默认为终端宽度,如果未连接到终端,则默认为 80 列,并且可以被 <width> 覆盖。 可以通过在逗号后给出另一个宽度 <name-width> 或设置 diff.statNameWidth=<name-width> 来限制文件名部分的宽度。 可以通过使用 --stat-graph-width=<graph-width> 或设置 diff.statGraphWidth=<graph-width> 来限制图形部分的宽度。 使用 --stat--stat-graph-width 会影响生成 stat 图的所有命令,而设置 diff.statNameWidthdiff.statGraphWidth 不会影响 git format-patch。 通过给出第三个参数 <count>,您可以将输出限制为前 <count> 行,如果还有更多行,则后面跟着 ...

这些参数也可以使用 --stat-width=<width>--stat-name-width=<name-width>--stat-count=<count> 单独设置。

--compact-summary

在 diffstat 中输出扩展的标头信息的压缩摘要,例如文件创建或删除(“new”或“gone”,如果是符号链接,则可选 +l)和模式更改(+x-x 分别表示添加或删除可执行位)。 该信息位于文件名部分和图形部分之间。 暗示 --stat

--numstat

类似于 --stat,但以十进制表示法显示添加和删除的行数,并显示没有缩写的路径名,使其更便于机器读取。 对于二进制文件,输出两个 - 而不是说 0 0

--shortstat

仅输出 --stat 格式的最后一行,其中包含修改的文件总数以及添加和删除的行数。

-X [<param>,...]
--dirstat[=<param>,...]

输出每个子目录的相对变化量的分布。 可以通过传递逗号分隔的参数列表来自定义 --dirstat 的行为。 默认值由 diff.dirstat 配置变量控制(请参阅 git-config[1])。 以下参数可用

changes

通过计算从源中删除或添加到目标的行来计算 dirstat 数字。 这忽略了文件中的纯代码移动量。 换句话说,重新排列文件中的行与其它更改的计数不同。 这是没有给出参数时的默认行为。

lines

通过执行基于行的常规 diff 分析并对删除/添加的行数进行求和来计算 dirstat 数字。(对于二进制文件,计数 64 字节的块,因为二进制文件没有行的自然概念)。这是一种比 changes 行为更昂贵的 --dirstat 行为,但它确实像其他更改一样计算文件中重新排列的行。 生成的输出与您从其他 --*stat 选项获得的输出一致。

files

通过计算更改的文件数来计算 dirstat 数字。 每个更改的文件在 dirstat 分析中都相等计数。 这是计算上最便宜的 --dirstat 行为,因为它根本不必查看文件内容。

cumulative

同时计算子目录的更改到父目录。请注意,当使用 cumulative 时,报告的百分比总和可能超过 100%。可以使用 noncumulative 参数指定默认(非累积)行为。

<limit>

整数参数指定一个截止百分比(默认为 3%)。更改贡献小于此百分比的目录不会显示在输出中。

例如:以下命令将计算已更改的文件,同时忽略已更改文件总数少于 10% 的目录,并将子目录计数累加到父目录中:--dirstat=files,10,cumulative

--cumulative

--dirstat=cumulative 的同义词。

--dirstat-by-file[=<param>,...]

--dirstat=files,<param>,... 的同义词。

--summary

输出扩展头信息的精简摘要,例如创建、重命名和模式更改。

--patch-with-stat

-p --stat 的同义词。

-z

当给出 --raw--numstat--name-only--name-status 时,不要修改路径名,并使用 NUL 作为输出字段的终止符。

如果没有此选项,包含“不寻常”字符的路径名将按照配置变量 core.quotePath 的说明进行引用(请参见 git-config[1])。

--name-only

仅显示 post-image 树中每个已更改文件的名称。 文件名通常以 UTF-8 编码。 更多信息请参阅 git-log[1] 手册页中关于编码的讨论。

--name-status

仅显示每个已更改文件的名称和状态。 有关状态字母含义的说明,请参阅 --diff-filter 选项的描述。与 --name-only 一样,文件名通常以 UTF-8 编码。

--submodule[=<format>]

指定如何显示子模块中的差异。 当指定 --submodule=short 时,将使用 short 格式。 此格式仅显示范围开始和结束时的提交名称。 当指定 --submodule--submodule=log 时,将使用 log 格式。 此格式列出范围内的提交,如 git-submodule[1] summary 一样。 当指定 --submodule=diff 时,将使用 diff 格式。 此格式显示提交范围内子模块内容更改的内联差异。 默认为 diff.submodule,如果未设置配置选项,则默认为 short 格式。

--color[=<when>]

显示彩色差异。 --color(即没有 =<when>)与 --color=always 相同。 <when> 可以是 alwaysneverauto 之一。

--no-color

关闭彩色差异。 它与 --color=never 相同。

--color-moved[=<mode>]

移动的代码行以不同的颜色显示。 如果未给出该选项,则 <mode> 默认为 no;如果给出了没有模式的选项,则默认为 zebra。 该模式必须是以下之一

no

不突出显示移动的行。

default

zebra 的同义词。 将来可能会更改为更合理的模式。

plain

在某个位置添加并且在另一个位置删除的任何行都将使用 color.diff.newMoved 着色。 类似地,color.diff.oldMoved 将用于在差异中的其他位置添加的已删除行。 此模式会拾取任何移动的行,但在审查中确定是否移动了一段代码而没有置换的情况下,它不是很有用。

blocks

贪婪地检测至少 20 个字母数字字符的移动文本块。 检测到的块使用 color.diff.(old|new)Moved 颜色绘制。 相邻的块无法区分。

zebra

blocks 模式检测移动的文本块。 这些块使用 color.diff.(old|new)Moved 颜色或 color.diff.(old|new)MovedAlternative 颜色绘制。 两种颜色之间的变化表示检测到新块。

dimmed-zebra

类似于 zebra,但对移动代码的不感兴趣的部分执行额外的变暗处理。 两个相邻块的边界线被认为是感兴趣的,其余的是不感兴趣的。 dimmed_zebra 是一个已弃用的同义词。

--no-color-moved

关闭移动检测。 这可用于覆盖配置设置。 它与 --color-moved=no 相同。

--color-moved-ws=<mode>,...

此配置控制在执行 --color-moved 的移动检测时如何忽略空格。 这些模式可以作为逗号分隔的列表给出

no

执行移动检测时不忽略空格。

ignore-space-at-eol

忽略 EOL 处的空格更改。

ignore-space-change

忽略空格数量的变化。 这会忽略行尾的空格,并将所有其他一个或多个空格字符的序列视为等效的。

ignore-all-space

比较行时忽略空格。 即使一行有空格而另一行没有空格,这也会忽略差异。

allow-indentation-change

最初忽略移动检测中的任何空格,然后仅当每行的空格变化相同才将移动的代码块分组到一个块中。 这与其他模式不兼容。

--no-color-moved-ws

执行移动检测时不忽略空格。 这可用于覆盖配置设置。 它与 --color-moved-ws=no 相同。

--word-diff[=<mode>]

默认情况下,单词由空格分隔;请参见下面的 --word-diff-regex<mode> 默认为 plain,并且必须是以下之一

color

仅使用颜色突出显示已更改的单词。 隐含 --color

plain

将单词显示为 [-removed-]{added}。 如果输入中出现分隔符,则不会尝试转义分隔符,因此输出可能不明确。

porcelain

使用一种特殊的基于行的格式,旨在供脚本使用。 添加/删除/未更改的运行以通常的统一差异格式打印,行首带有 +/-/` ` 字符,并延伸到行尾。 输入中的换行符由其自身行上的波浪号 ~ 表示。

none

再次禁用单词差异。

请注意,尽管第一个模式的名称如此,但如果启用,颜色用于突出显示所有模式中的已更改部分。

--word-diff-regex=<regex>

使用 <regex> 来决定什么是一个单词,而不是将非空格的运行视为一个单词。 除非已经启用,否则也隐含 --word-diff

<regex> 的每个非重叠匹配项都被认为是一个单词。 这些匹配项之间的任何内容都被认为是空格,并且为了查找差异的目的而被忽略(!)。 您可能想要将 |[^[:space:]] 附加到您的正则表达式,以确保它匹配所有非空格字符。 包含换行符的匹配项会在换行符处被静默截断(!)。

例如,--word-diff-regex=. 会将每个字符视为一个单词,并相应地逐个字符地显示差异。

正则表达式也可以通过差异驱动程序或配置选项进行设置,请参见 gitattributes[5]git-config[1]。 显式给出它会覆盖任何差异驱动程序或配置设置。 差异驱动程序会覆盖配置设置。

--color-words[=<regex>]

等效于 --word-diff=color 加上(如果指定了正则表达式)--word-diff-regex=<regex>

--no-renames

关闭重命名检测,即使配置文件给出了默认值也是如此。

--[no-]rename-empty

是否使用空 blob 作为重命名源。

--check

如果更改引入冲突标记或空格错误,则发出警告。 被认为是空格错误的内容由 core.whitespace 配置控制。 默认情况下,尾随空格(包括仅由空格组成的行)以及紧跟在行初始缩进中的制表符之前的空格字符被认为是空格错误。 如果发现问题,则以非零状态退出。 与 --exit-code 不兼容。

--ws-error-highlight=<kind>

突出显示差异的 contextoldnew 行中的空格错误。 多个值用逗号分隔,none 重置先前的值,default 将列表重置为 newallold,new,context 的简写形式。 如果未给出此选项,并且未设置配置变量 diff.wsErrorHighlight,则仅突出显示 new 行中的空格错误。 空格错误使用 color.diff.whitespace 着色。

--full-index

在生成补丁格式输出时,在“index”行上显示完整的 pre- 和 post-image blob 对象名称,而不是前几个字符。

--binary

除了 --full-index 之外,还输出一个二进制差异,可以用 git-apply 应用。隐含 --patch

--abbrev[=<n>]

不在 diff-raw 格式输出和 diff-tree 头部行中显示完整的 40 字节十六进制对象名称,而是显示至少 <n> 个十六进制数字长的最短前缀,该前缀唯一地引用该对象。在 diff-patch 输出格式中,--full-index 具有更高的优先级,即如果指定了 --full-index,则将显示完整的 blob 名称,而不管 --abbrev 如何。可以使用 --abbrev=<n> 指定非默认的位数。

-B[<n>][/<m>]
--break-rewrites[=[<n>][/<m>]]

将完全重写更改分解为删除和创建的对。这有两个目的

它影响了对文件完全重写的更改的处理方式,不再是将删除和插入混合在一起,并带有少量与上下文在文本上匹配的行,而是将其视为删除所有旧内容,然后插入所有新内容,数字 <m> 控制 -B 选项的这方面(默认为 60%)。-B/70% 指定原始内容中保留的内容少于 30% 时,Git 才会将其视为完全重写(即,否则生成的补丁将是一系列删除和插入与上下文行混合在一起)。

-M 一起使用时,完全重写的文件也被认为是重命名的来源(通常 -M 仅将消失的文件视为重命名的来源),数字 <n> 控制 -B 选项的这方面(默认为 50%)。-B20% 指定与文件大小相比添加和删除超过 20% 的更改有资格被选作可能重命名到另一个文件的来源。

-M[<n>]
--find-renames[=<n>]

检测重命名。如果指定了 <n>,则它是相似度索引的阈值(即与文件大小相比的添加/删除量)。例如,-M90% 表示如果文件未更改超过 90%,Git 应考虑删除/添加对为重命名。如果没有 % 符号,则该数字应被视为小数,小数点位于其前面。也就是说,-M5 变为 0.5,因此与 -M50% 相同。类似地,-M05-M5% 相同。要将检测限制为完全重命名,请使用 -M100%。默认相似度索引为 50%。

-C[<n>]
--find-copies[=<n>]

检测副本以及重命名。另请参阅 --find-copies-harder。如果指定了 <n>,则其含义与 -M<n> 相同。

--find-copies-harder

出于性能原因,默认情况下,仅当副本的原始文件在同一变更集中被修改时,-C 选项才会查找副本。此标志使命令检查未修改的文件作为副本的来源的候选对象。对于大型项目来说,这是一个非常昂贵的操作,因此请谨慎使用。给出多个 -C 选项具有相同的效果。

-D
--irreversible-delete

省略删除的 preimage,即仅打印头部,而不打印 preimage 和 /dev/null 之间的差异。生成的补丁不打算与 patchgit apply 一起应用;这仅适用于只想专注于审查更改后文本的人员。此外,输出显然缺少足够的信息来反向应用这样的补丁,即使是手动应用,因此得名该选项。

-B 一起使用时,也省略删除/创建对的删除部分的 preimage。

-l<num>

-M-C 选项涉及一些初步步骤,可以廉价地检测重命名/副本的子集,然后是一个详尽的回退部分,将所有剩余的未配对目标与所有相关的源进行比较。(对于重命名,仅剩余的未配对源是相关的;对于副本,所有原始源都是相关的。)对于 N 个源和目标,此详尽的检查是 O(N^2)。如果涉及的源/目标文件数超过指定的数字,此选项可防止运行重命名/副本检测的详尽部分。默认为 diff.renameLimit。请注意,值 0 被视为无限制。

--diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]

仅选择已添加 (A)、已复制 (C)、已删除 (D)、已修改 (M)、已重命名 (R)、其类型(即常规文件、符号链接、子模块……)已更改 (T)、未合并 (U)、未知 (X) 或其配对已损坏 (B) 的文件。可以使用过滤器字符的任何组合(包括无)。当 *(全部或无)添加到组合中时,如果比较中存在任何与其它条件匹配的文件,则选择所有路径;如果没有与其它条件匹配的文件,则不选择任何内容。

此外,这些大写字母可以小写以排除。例如,--diff-filter=ad 排除已添加和已删除的路径。

请注意,并非所有差异都可以包含所有类型。例如,如果禁用这些类型的检测,则不会出现复制和重命名的条目。

-S<string>

查找更改文件中指定 <string> 的出现次数(即添加/删除)的差异。旨在供脚本编写者使用。

当您寻找一段精确的代码块(如结构)时,并且想知道该代码块自诞生以来的历史记录时,此功能非常有用:迭代使用该功能将 preimage 中的有趣块反馈回 -S,并继续操作,直到获得该块的第一个版本。

也会搜索二进制文件。

-G<regex>

查找补丁文本包含与 <regex> 匹配的添加/删除行的差异。

为了说明 -S<regex> --pickaxe-regex-G<regex> 之间的区别,请考虑一个提交,该提交在同一文件中具有以下差异

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

虽然 git log -G"frotz\(nitfol" 将显示此提交,但 git log -S"frotz\(nitfol" --pickaxe-regex 不会(因为该字符串的出现次数没有改变)。

除非提供了 --text,否则将忽略没有 textconv 过滤器的二进制文件的补丁。

有关更多信息,请参阅 gitdiffcore[7] 中的 *pickaxe* 条目。

--find-object=<object-id>

查找更改指定对象的出现次数的差异。类似于 -S,只是参数不同,它不搜索特定字符串,而是搜索特定对象 id。

该对象可以是 blob 或子模块提交。它意味着 git-log 中的 -t 选项也查找树。

--pickaxe-all

-S-G 找到更改时,显示该变更集中的所有更改,而不仅仅是包含 <string> 中更改的文件。

--pickaxe-regex

将提供给 -S<string> 视为要匹配的扩展 POSIX 正则表达式。

-O<orderfile>

控制文件在输出中出现的顺序。这将覆盖 diff.orderFile 配置变量(请参阅 git-config[1])。要取消 diff.orderFile,请使用 -O/dev/null

输出顺序由 <orderfile> 中 glob 模式的顺序决定。首先输出所有路径名与第一个模式匹配的文件,接下来输出所有路径名与第二个模式匹配的文件(但不与第一个模式匹配),依此类推。最后输出所有路径名与任何模式都不匹配的文件,就像文件末尾有一个隐式的全部匹配模式一样。如果多个路径名具有相同的等级(它们匹配相同的模式但不匹配更早的模式),则它们相对于彼此的输出顺序是正常顺序。

<orderfile> 的解析方式如下

  • 忽略空行,因此可以将它们用作分隔符以提高可读性。

  • 忽略以哈希("#")开头的行,因此可以将它们用于注释。如果模式以哈希开头,请在模式开头添加反斜杠("\")。

  • 每个其他行包含一个模式。

模式具有与用于 fnmatch(3) 的模式相同的语法和语义,但没有 FNM_PATHNAME 标志,除非如果删除任何数量的最终路径名组件与模式匹配,则路径名也与模式匹配。例如,模式 "foo*bar" 匹配 "fooasdfbar" 和 "foo/bar/baz/asdf" 但不匹配 "foobarx"。

--skip-to=<file>
--rotate-to=<file>

从输出中丢弃指定 <file> 之前的文件(即*跳到*),或将它们移动到输出的末尾(即*旋转到*)。这些选项主要为 git difftool 命令的使用而发明,否则可能不是很有用。

-R

交换两个输入;也就是说,显示从索引或磁盘文件到树内容的差异。

--relative[=<path>]
--no-relative

从项目的子目录运行时,可以使用此选项告诉它排除目录外的更改并显示相对于该目录的路径名。当您不在子目录中时(例如,在裸存储库中),您可以通过提供 <path> 作为参数来命名要使输出相对于哪个子目录。--no-relative 可用于取消 diff.relative 配置选项和之前的 --relative

-a
--text

将所有文件视为文本。

--ignore-cr-at-eol

在进行比较时,忽略行尾的回车符。

--ignore-space-at-eol

忽略 EOL 处的空格更改。

-b
--ignore-space-change

忽略空格数量的变化。 这会忽略行尾的空格,并将所有其他一个或多个空格字符的序列视为等效的。

-w
--ignore-all-space

比较行时忽略空格。 即使一行有空格而另一行没有空格,这也会忽略差异。

--ignore-blank-lines

忽略所有行都是空白的更改。

-I<regex>
--ignore-matching-lines=<regex>

忽略所有行都匹配 *<regex>* 的更改。可以多次指定此选项。

--inter-hunk-context=<number>

显示差异块之间的上下文,最多显示指定的 *<number>* 行,从而融合彼此靠近的块。默认值为 diff.interHunkContext,如果未设置配置选项,则为 0。

-W
--function-context

将整个函数显示为每个更改的上下文行。函数名称的确定方式与 git diff 计算补丁块标头的方式相同(请参阅 gitattributes[5] 中的“定义自定义块标头”)。

--exit-code

使程序以类似于 diff(1) 的代码退出。也就是说,如果有差异,则以 1 退出,0 表示没有差异。

--quiet

禁用程序的所有输出。暗示 --exit-code。禁用退出代码不可信的外部差异帮助程序的执行,即它们各自的配置选项 diff.trustExitCodediff.<driver>.trustExitCode 或环境变量 GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE 为 false。

--ext-diff

允许执行外部差异助手。如果使用 gitattributes[5] 设置了外部差异驱动程序,则需要将此选项与 git-log[1] 及其关联命令一起使用。

--no-ext-diff

不允许使用外部差异驱动程序。

--textconv
--no-textconv

允许(或禁止)在比较二进制文件时运行外部文本转换过滤器。有关详细信息,请参阅 gitattributes[5]。由于 textconv 过滤器通常是单向转换,因此生成的差异适合人眼查看,但无法应用。因此,textconv 过滤器默认仅为 git-diff[1]git-log[1] 启用,但不为 git-format-patch[1] 或差异管道命令启用。

--ignore-submodules[=(none|untracked|dirty|all)]

忽略差异生成中对子模块的更改。all 是默认值。使用 none 将在子模块包含未跟踪或修改的文件或其 HEAD 与超级项目中记录的提交不同时,认为子模块已被修改,并且可用于覆盖 git-config[1]gitmodules[5]ignore 选项的任何设置。使用 untracked 时,如果子模块仅包含未跟踪的内容,则不会将其视为脏状态(但仍会扫描已修改的内容)。使用 dirty 会忽略对子模块工作树的所有更改,仅显示对存储在超级项目中的提交的更改(这是 1.7.0 之前的行为)。使用 all 会隐藏对子模块的所有更改。

--src-prefix=<prefix>

显示给定的源 *<prefix>*,而不是 "a/"。

--dst-prefix=<prefix>

显示给定的目标 *<prefix>*,而不是 "b/"。

--no-prefix

不显示任何源或目标前缀。

--default-prefix

使用默认的源和目标前缀("a/" 和 "b/")。这会覆盖配置变量,例如 diff.noprefixdiff.srcPrefixdiff.dstPrefixdiff.mnemonicPrefix(请参阅 git-config[1])。

--line-prefix=<prefix>

在每行输出前添加一个额外的 *<prefix>*。

--ita-invisible-in-index

默认情况下,由 git add -N 添加的条目在 git diff 中显示为现有空文件,在 git diff --cached 中显示为新文件。此选项使条目在 git diff 中显示为新文件,在 git diff --cached 中显示为不存在的文件。可以使用 --ita-visible-in-index 还原此选项。这两个选项都是实验性的,可能会在将来删除。

有关这些常用选项的更详细说明,另请参阅 gitdiffcore[7]

<tree-ish>

树对象的 ID。

<path>…​

如果提供,则结果仅限于与提供的路径规范之一匹配的文件子集。

-r

递归到子树中。

-t

同时显示树条目本身和子树。暗示 -r。

--root

指定 --root 时,初始提交将显示为大型创建事件。这相当于对 NULL 树的差异。

--merge-base

不直接比较 <tree-ish>,而是使用两个 <tree-ish> 之间的合并基础作为“之前”端。必须提供两个 <tree-ish>,并且它们都必须是提交。

--stdin

指定 --stdin 时,命令不会从命令行获取 <tree-ish> 参数。而是从其标准输入中读取包含两个 <tree>、一个 <commit> 或 <commit> 列表的行。(使用单个空格作为分隔符。)

当给出两个树时,它会将第一个树与第二个树进行比较。当给出单个提交时,它会将提交与其父提交进行比较。当给出剩余的提交时,它们的用法就像是第一个提交的父提交。

比较两个树时,差异之前会打印两个树的 ID(以空格分隔并以换行符结尾)。比较提交时,会打印第一个(或唯一)提交的 ID,后跟换行符。

以下标志会进一步影响比较提交时的行为(但不影响树)。

-m

默认情况下,*git diff-tree --stdin* 不显示合并提交的差异。使用此标志,它会显示该提交与其所有父提交的差异。另请参阅 -c

-s

默认情况下,*git diff-tree --stdin* 以机器可读格式(不带 -p)或补丁格式(带 -p)显示差异。此输出可以被抑制。它仅在使用 -v 标志时有用。

-v

此标志使 *git diff-tree --stdin* 还在差异之前显示提交消息。

--pretty[=<format>]
--format=<format>

以给定格式美化打印提交日志的内容,其中 *<format>* 可以是 *oneline*、*short*、*medium*、*full*、*fuller*、*reference*、*email*、*raw*、*format:<string>* 和 *tformat:<string>* 之一。当 *<format>* 不是上述任何一种,并且其中包含 *%placeholder* 时,它的作用类似于给定了 *--pretty=tformat:<format>*。

有关每种格式的更多详细信息,请参阅“美化格式”部分。省略 *=<format>* 部分时,默认为 *medium*。

注意:您可以在存储库配置中指定默认的美化格式(请参阅 git-config[1])。

--abbrev-commit

不显示完整的 40 字节十六进制提交对象名称,而是显示唯一命名该对象的前缀。可以使用“--abbrev=<n>”(如果显示差异,也会修改差异输出)选项来指定前缀的最小长度。

这应该使对于使用 80 列终端的人来说,“--pretty=oneline”更具可读性。

--no-abbrev-commit

显示完整的 40 字节十六进制提交对象名称。这否定了 --abbrev-commit,无论是显式的还是由其他选项(例如“--oneline”)暗示的。它还覆盖了 log.abbrevCommit 变量。

--oneline

这是“--pretty=oneline --abbrev-commit”一起使用的简写形式。

--encoding=<encoding>

提交对象在其编码标头中记录用于日志消息的字符编码;此选项可用于告诉命令以用户首选的编码重新编码提交日志消息。对于非管道命令,默认为 UTF-8。请注意,如果对象声称以 X 编码,并且我们以 X 输出,我们将逐字输出该对象;这意味着原始提交中的无效序列可能会被复制到输出中。同样,如果 iconv(3) 无法转换提交,我们将静默地逐字输出原始对象。

--expand-tabs=<n>
--expand-tabs
--no-expand-tabs

在输出中显示日志消息之前,执行制表符扩展(用足够的空格替换每个制表符,以填充到下一个显示列,该列是 *<n>* 的倍数)。--expand-tabs--expand-tabs=8 的简写形式,--no-expand-tabs--expand-tabs=0 的简写形式,它禁用制表符扩展。

默认情况下,制表符在将日志消息缩进 4 个空格的美化格式中展开(即 *medium*(默认)、*full* 和 *fuller*)。

--notes[=<ref>]

显示注释提交的注释(请参阅 git-notes[1]),并在显示提交日志消息时显示。当命令行上没有给出 --pretty--format--oneline 选项时,这是 git loggit showgit whatchanged 命令的默认设置。

默认情况下,显示的注释来自 core.notesRefnotes.displayRef 变量(或相应的环境覆盖)中列出的注释引用。有关更多详细信息,请参阅 git-config[1]

对于可选的 *<ref>* 参数,使用该引用来查找要显示的注释。当引用以 refs/notes/ 开头时,它可以指定完整的引用名称;当它以 notes/ 开头时,将添加前缀 refs/,否则将添加前缀 refs/notes/ 以形成引用的完整名称。

可以组合多个 --notes 选项来控制要显示的注释。例如:“--notes=foo”将仅显示来自“refs/notes/foo”的注释;“--notes=foo --notes”将同时显示来自“refs/notes/foo”和默认注释引用(ref)的注释。

--no-notes

不显示注释。这会否定上面的 --notes 选项,通过重置从中显示注释的注释引用列表。选项按照在命令行中给出的顺序进行解析,因此例如“--notes --notes=foo --no-notes --notes=bar”将仅显示来自“refs/notes/bar”的注释。

--show-notes-by-default

显示默认注释,除非给出了用于显示特定注释的选项。

--show-notes[=<ref>]
--[no-]standard-notes

这些选项已弃用。请改用上面的 --notes/--no-notes 选项。

--show-signature

通过将签名传递给 gpg --verify 来检查已签名提交对象的有效性,并显示输出。

--no-commit-id

git diff-tree 在适用时输出带有提交 ID 的行。此标志会抑制提交 ID 输出。

-c

此标志更改了合并提交的显示方式(这意味着它仅在命令给定一个 <tree-ish> 或 --stdin 时才有用)。它同时显示每个父级与合并结果之间的差异,而不是一次显示父级与结果之间的成对差异(这是 -m 选项的作用)。此外,它仅列出从所有父级修改过的文件。

--cc

此标志以类似于 -c 选项的方式更改合并提交补丁的显示方式。它暗示了 -c-p 选项,并通过省略在父级中内容只有两个变体并且合并结果未经修改地选择了其中一个变体的无趣的块来进一步压缩补丁输出。当所有块都无趣时,提交本身和提交日志消息都不会显示,就像在任何其他“空差异”情况下一样。

--combined-all-paths

此标志使组合差异(用于合并提交)列出所有父级中的文件名。因此,它仅在指定 -c 或 --cc 时才有效,并且可能仅在检测到文件名更改时才有用(即,当已请求重命名或复制检测时)。

--always

即使差异本身为空,也显示提交本身和提交日志消息。

美化格式

如果提交是合并,并且如果美化格式不是 *oneline*、*email* 或 *raw*,则在 *Author:* 行之前插入一个附加行。此行以“Merge: ”开头,并打印祖先提交的哈希值,以空格分隔。请注意,如果您限制了历史视图,则列出的提交可能不一定是 **直接** 父提交的列表:例如,如果您只对与某个目录或文件相关的更改感兴趣。

有几种内置格式,您可以通过将 pretty.<name> 配置选项设置为另一个格式名称或 *format:* 字符串来定义其他格式,如下所述(请参阅 git-config[1])。以下是内置格式的详细信息

  • oneline

    <hash> <title-line>

    旨在尽可能紧凑。

  • short

    commit <hash>
    Author: <author>
    <title-line>
  • medium

    commit <hash>
    Author: <author>
    Date:   <author-date>
    <title-line>
    <full-commit-message>
  • full

    commit <hash>
    Author: <author>
    Commit: <committer>
    <title-line>
    <full-commit-message>
  • fuller

    commit <hash>
    Author:     <author>
    AuthorDate: <author-date>
    Commit:     <committer>
    CommitDate: <committer-date>
    <title-line>
    <full-commit-message>
  • reference

    <abbrev-hash> (<title-line>, <short-author-date>)

    此格式用于在提交消息中引用另一个提交,并且与 --pretty='format:%C(auto)%h (%s, %ad)' 相同。默认情况下,日期使用 --date=short 格式化,除非显式指定了另一个 --date 选项。与任何带有格式占位符的 format: 一样,它的输出不受其他选项的影响,例如 --decorate--walk-reflogs

  • email

    From <hash> <date>
    From: <author>
    Date: <author-date>
    Subject: [PATCH] <title-line>
    <full-commit-message>
  • mboxrd

    与 *email* 类似,但以“From ”开头的提交消息中的行(以零个或多个“>”开头)用“>”引用,因此它们不会被误认为是开始了新的提交。

  • raw

    raw 格式完全按照存储在提交对象中的方式显示整个提交。值得注意的是,哈希值以完整形式显示,无论是否使用 --abbrev 或 --no-abbrev,并且 *parents* 信息显示真实的父提交,而不考虑 grafts 或历史简化。请注意,此格式会影响提交的显示方式,但不会影响差异的显示方式,例如使用 git log --raw。要在原始差异格式中获取完整的对象名称,请使用 --no-abbrev

  • format:<format-string>

    format:<format-string> 格式允许您指定要显示的信息。它的工作方式有点像 printf 格式,但值得注意的是,您可以使用 %n 而不是 \n 来获取换行符。

    例如,format:"The author of %h was %an, %ar%nThe title was >>%s<<%n" 将显示如下内容

    The author of fe6e0ee was Junio C Hamano, 23 hours ago
    The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<

    占位符是

    • 扩展为单个文字字符的占位符

      %n

      换行符

      %%

      原始的 %

      %x00

      %x 后跟两个十六进制数字将替换为具有十六进制数字值的字节(我们将在本文档的其余部分中将其称为“文字格式代码”)。

    • 影响稍后占位符格式的占位符

      %Cred

      将颜色切换为红色

      %Cgreen

      将颜色切换为绿色

      %Cblue

      将颜色切换为蓝色

      %Creset

      重置颜色

      %C(…​)

      颜色规范,如 git-config[1] 的“配置文件”部分中的值中所述。 默认情况下,仅当为日志输出启用颜色时才显示颜色(通过 color.diffcolor.ui--color,并且如果我们转到终端,则遵循前者的 auto 设置)。 %C(auto,...) 被接受为默认值的历史同义词(例如,%C(auto,red))。 指定 %C(always,...) 即使在未启用颜色时也会显示颜色(尽管请考虑仅使用 --color=always 来为整个输出启用颜色,包括此格式和 git 可能着色的任何其他内容)。 单独的 auto(即 %C(auto))将打开下一个占位符的自动着色,直到再次切换颜色为止。

      %m

      左 (<)、右 (>) 或边界 (-) 标记

      %w([<w>[,<i1>[,<i2>]]])

      切换换行,类似于 git-shortlog[1] 的 -w 选项。

      %<( <N> [,trunc|ltrunc|mtrunc])

      使下一个占位符至少占用 N 列的宽度,并在必要时在右侧填充空格。如果输出长于 N 列,则可以选择在左侧 (ltrunc) ..ft、中间 (mtrunc) mi..le 或结尾 (trunc) rig.. 处截断(用省略号 ..)。注意 1:截断仅在 N >= 2 时才能正确工作。注意 2:N 和 M(见下文)值周围的空格是可选的。注意 3:表情符号和其他宽字符将占用两个显示列,这可能会超出列边界。注意 4:分解的字符组合标记可能会在填充边界处错位。

      %<|( <M> )

      使下一个占位符至少占用到第 M 个显示列,并在必要时在右侧填充空格。对从终端窗口右侧边缘测量的列位置使用负 M 值。

      %>( <N> ), %>|( <M> )

      分别类似于 %<( <N> )%<|( <M> ),但在左侧填充空格

      %>>( <N> ), %>>|( <M> )

      分别类似于 %>( <N> )%>|( <M> ),但如果下一个占位符占用的空间多于给定空间并且其左侧有空格,则使用这些空格

      %><( <N> ), %><|( <M> )

      分别类似于 %<( <N> )%<|( <M> ),但在两侧填充空格(即文本居中)

    • 扩展为从提交中提取的信息的占位符

      %H

      提交哈希

      %h

      缩写的提交哈希

      %T

      树哈希

      %t

      缩写的树哈希

      %P

      父哈希

      %p

      缩写的父哈希

      %an

      作者姓名

      %aN

      作者姓名(尊重 .mailmap,请参阅 git-shortlog[1]git-blame[1]

      %ae

      作者电子邮件

      %aE

      作者电子邮件(尊重 .mailmap,请参阅 git-shortlog[1]git-blame[1]

      %al

      作者电子邮件本地部分(@ 符号之前的部分)

      %aL

      作者本地部分(请参阅 %al),尊重 .mailmap,请参阅 git-shortlog[1]git-blame[1]

      %ad

      作者日期(格式尊重 --date= 选项)

      %aD

      作者日期,RFC2822 样式

      %ar

      作者日期,相对

      %at

      作者日期,UNIX 时间戳

      %ai

      作者日期,类似于 ISO 8601 的格式

      %aI

      作者日期,严格的 ISO 8601 格式

      %as

      作者日期,短格式 (YYYY-MM-DD)

      %ah

      作者日期,人类可读风格 (类似 git-rev-list[1]--date=human 选项)

      %cn

      提交者姓名

      %cN

      提交者姓名 (遵循 .mailmap,参见 git-shortlog[1]git-blame[1])

      %ce

      提交者邮箱

      %cE

      提交者邮箱 (遵循 .mailmap,参见 git-shortlog[1]git-blame[1])

      %cl

      提交者邮箱本地部分 (@ 符号之前的部分)

      %cL

      提交者本地部分 (参见 %cl) 遵循 .mailmap,参见 git-shortlog[1]git-blame[1])

      %cd

      提交者日期 (格式遵循 --date= 选项)

      %cD

      提交者日期,RFC2822 风格

      %cr

      提交者日期,相对时间

      %ct

      提交者日期,UNIX 时间戳

      %ci

      提交者日期,类似于 ISO 8601 的格式

      %cI

      提交者日期,严格的 ISO 8601 格式

      %cs

      提交者日期,短格式 (YYYY-MM-DD)

      %ch

      提交者日期,人类可读风格 (类似 git-rev-list[1]--date=human 选项)

      %d

      引用名称,类似 git-log[1] 的 --decorate 选项

      %D

      不带 " (", ")" 包裹的引用名称。

      %(decorate[:<options>])

      具有自定义修饰的引用名称。decorate 字符串后可以跟一个冒号和零个或多个逗号分隔的选项。选项值可以包含文字格式代码。由于它们在选项语法中的作用,这些代码必须用于逗号 (%x2C) 和右括号 (%x29)。

      • prefix=<value>:在引用名称列表之前显示。默认为 " ("。

      • suffix=<value>:在引用名称列表之后显示。默认为 ")"。

      • separator=<value>:在引用名称之间显示。默认为 ", "。

      • pointer=<value>:如果 HEAD 指向分支,则在 HEAD 和其指向的分支之间显示。默认为 " -> "。

      • tag=<value>:在标签名称之前显示。默认为 "tag: "。

    例如,要生成没有包裹或标签注释,并且空格作为分隔符的修饰:

    + %(decorate:prefix=,suffix=,tag=,separator= )

    %(describe[:<options>])

    人类可读的名称,类似 git-describe[1];对于无法描述的提交,则为空字符串。 describe 字符串后可以跟一个冒号和零个或多个逗号分隔的选项。当同时添加或删除标签时,描述可能不一致。

    • tags[=<bool-value>]:除了考虑带注释的标签外,还考虑轻量级标签。

    • abbrev=<number>:不使用缩写对象名称的默认十六进制数字位数(默认情况下,该位数会根据存储库中对象的数量而变化,默认为 7),而是使用 <number> 位数字,或形成唯一对象名称所需的位数。

    • match=<pattern>:仅考虑与给定的 glob(7) 模式匹配的标签,不包括 "refs/tags/" 前缀。

    • exclude=<pattern>:不考虑与给定的 glob(7) 模式匹配的标签,不包括 "refs/tags/" 前缀。

    %S

    命令行上给出的,通过哪个引用名称到达该提交 (类似 git log --source),仅适用于 git log

    %e

    编码

    %s

    主题

    %f

    经过处理的主题行,适合作为文件名

    %b

    正文

    %B

    原始正文 (未换行的主题和正文)

    %N

    提交说明

    %GG

    来自 GPG 的原始验证消息,用于已签名的提交

    %G?

    对于有效签名显示 "G",对于错误签名显示 "B",对于具有未知有效性的有效签名显示 "U",对于已过期的有效签名显示 "X",对于由已过期的密钥进行的有效签名显示 "Y",对于由已撤销的密钥进行的有效签名显示 "R",如果无法检查签名(例如,缺少密钥)显示 "E",对于没有签名显示 "N"

    %GS

    显示已签名提交的签名者姓名

    %GK

    显示用于签署已签名提交的密钥

    %GF

    显示用于签署已签名提交的密钥的指纹

    %GP

    显示用于签署已签名提交的子密钥所属主密钥的指纹

    %GT

    显示用于签署已签名提交的密钥的信任级别

    %gD

    reflog 选择器,例如,refs/stash@{1}refs/stash@{2 minutes ago};格式遵循为 -g 选项描述的规则。@ 之前的部分是在命令行上给出的 refname(因此 git log -g refs/heads/master 将产生 refs/heads/master@{0})。

    %gd

    缩短的 reflog 选择器;与 %gD 相同,但 refname 部分缩短以提高人类可读性(因此 refs/heads/master 变为 master)。

    %gn

    reflog 身份名称

    %gN

    reflog 身份名称 (遵循 .mailmap,参见 git-shortlog[1]git-blame[1])

    %ge

    reflog 身份邮箱

    %gE

    reflog 身份邮箱 (遵循 .mailmap,参见 git-shortlog[1]git-blame[1])

    %gs

    reflog 主题

    %(trailers[:<options>])

    显示正文的 trailers,由 git-interpret-trailers[1] 解释。trailers 字符串后可以跟一个冒号和零个或多个逗号分隔的选项。如果多次提供任何选项,则最后一个出现项获胜。

    • key=<key>:仅显示具有指定 <key> 的 trailers。匹配不区分大小写,并且尾随冒号是可选的。如果多次给出该选项,则会显示与任何键匹配的 trailer 行。此选项会自动启用 only 选项,以便隐藏 trailer 块中的非 trailer 行。如果不需要这样做,可以使用 only=false 禁用它。例如,%(trailers:key=Reviewed-by) 显示具有键 Reviewed-by 的 trailer 行。

    • only[=<bool>]:选择是否应包含来自 trailer 块的非 trailer 行。

    • separator=<sep>:指定插入在 trailer 行之间的分隔符。默认为换行符。字符串 <sep> 可以包含上述文字格式代码。要使用逗号作为分隔符,必须使用 %x2C,否则它将被解析为下一个选项。例如,%(trailers:key=Ticket,separator=%x2C ) 显示所有键为 "Ticket" 的 trailer 行,并以逗号和空格分隔。

    • unfold[=<bool>]:使其行为就像给出了 interpret-trailer 的 --unfold 选项一样。例如,%(trailers:only,unfold=true) 展开并显示所有 trailer 行。

    • keyonly[=<bool>]:仅显示 trailer 的键部分。

    • valueonly[=<bool>]:仅显示 trailer 的值部分。

    • key_value_separator=<sep>:指定插入在每个 trailer 的键和值之间的分隔符。默认为 ": "。否则,它与上面的 separator=<sep> 具有相同的语义。

注意
某些占位符可能取决于提供给修订遍历引擎的其他选项。例如,%g* reflog 选项将插入一个空字符串,除非我们正在遍历 reflog 条目(例如,通过 git log -g)。如果命令行上尚未提供 --decorate,则 %d%D 占位符将使用“short”修饰格式。

布尔选项接受可选值 [=<bool-value>]--type=bool git-config[1] 采用的值(如 yesoff)都被接受。不带 =<value> 提供布尔选项等效于使用 =true 提供它。

如果在占位符的 % 之后添加一个 + (加号),那么只有当占位符扩展为一个非空字符串时,才会在扩展之前立即插入一个换行符。

如果在占位符的 % 之后添加一个 - (减号),那么只有当占位符扩展为一个空字符串时,才会删除扩展之前的所有连续换行符。

如果在占位符的 % 之后添加一个 ` ` (空格),那么只有当占位符扩展为一个非空字符串时,才会在扩展之前立即插入一个空格。

  • tformat

    tformat: 格式的工作方式与 format: 完全相同,只不过它提供的是“终止符”语义,而不是“分隔符”语义。换句话说,每个提交都会附加消息终止符(通常是换行符),而不是在条目之间放置分隔符。这意味着单行格式的最后一个条目将使用换行符正确终止,就像“oneline”格式一样。 例如

    $ git log -2 --pretty=format:%h 4da45bef \
      | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/'
    4da45be
    7134973 -- NO NEWLINE
    
    $ git log -2 --pretty=tformat:%h 4da45bef \
      | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/'
    4da45be
    7134973

    此外,任何包含 % 的无法识别的字符串都将被解释为前面带有 tformat:。例如,以下两者是等效的

    $ git log -2 --pretty=tformat:%h 4da45bef
    $ git log -2 --pretty=%h 4da45bef

原始输出格式

来自 git-diff-indexgit-diff-treegit-diff-filesgit diff --raw 的原始输出格式非常相似。

这些命令都比较两组事物;比较的内容有所不同

git-diff-index <tree-ish>

比较 <tree-ish> 和文件系统上的文件。

git-diff-index --cached <tree-ish>

比较 <tree-ish> 和索引。

git-diff-tree [-r] <tree-ish-1> <tree-ish-2> [<pattern>...]

比较由两个参数命名的树。

git-diff-files [<pattern>...]

比较索引和文件系统上的文件。

git-diff-tree 命令首先打印正在比较的内容的哈希值作为其输出的开始。 之后,所有命令都为每个已更改的文件打印一行输出。

输出行的格式如下

in-place edit  :100644 100644 bcd1234 0123456 M file0
copy-edit      :100644 100644 abcd123 1234567 C68 file1 file2
rename-edit    :100644 100644 abcd123 1234567 R86 file1 file3
create         :000000 100644 0000000 1234567 A file4
delete         :100644 000000 1234567 0000000 D file5
unmerged       :000000 000000 0000000 0000000 U file6

也就是说,从左到右

  1. 一个冒号。

  2. “src”的模式; 如果是创建或未合并,则为 000000。

  3. 一个空格。

  4. “dst”的模式; 如果是删除或未合并,则为 000000。

  5. 一个空格。

  6. “src”的 sha1; 如果是创建或未合并,则为 0{40}。

  7. 一个空格。

  8. “dst”的 sha1; 如果是删除、未合并或“工作树与索引不同步”,则为 0{40}。

  9. 一个空格。

  10. 状态,后跟可选的“得分”数字。

  11. 当使用 -z 选项时,一个制表符或一个 NUL。

  12. “src”的路径

  13. 当使用 -z 选项时,一个制表符或一个 NUL; 仅对于 C 或 R 存在。

  14. “dst”的路径; 仅对于 C 或 R 存在。

  15. 当使用 -z 选项时,一个 LF 或一个 NUL,用于终止记录。

可能的地位字母是

  • A:添加文件

  • C:将文件复制到新文件中

  • D:删除文件

  • M:修改文件的内容或模式

  • R:重命名文件

  • T:更改文件的类型(常规文件、符号链接或子模块)

  • U:文件未合并(您必须先完成合并才能提交)

  • X:“未知”更改类型(很可能是一个错误,请报告它)

状态字母 CR 始终后跟一个分数(表示移动或复制的源和目标之间的相似性百分比)。 状态字母 M 之后可以跟一个分数(表示文件重写的不同之处的百分比)。

如果文件系统上的文件与索引不同步,则“dst”的 sha1 显示为全 0。

例子

:100644 100644 5be4a4a 0000000 M file.c

如果没有 -z 选项,则包含“不寻常”字符的路径名将按照配置变量 core.quotePath 的说明进行引用(请参阅 git-config[1])。 使用 -z 时,文件名将逐字输出,并且行以 NUL 字节终止。

合并的差异格式

git-diff-treegit-diff-filesgit-diff --raw 可以使用 -c--cc 选项来为合并提交生成差异输出。 该输出与上述格式的不同之处在于

  1. 每个父级都有一个冒号

  2. 有更多的“src”模式和“src”sha1

  3. 状态是每个父级的连接状态字符

  4. 没有可选的“得分”数字

  5. 文件的制表符分隔的路径名

对于 -c--cc,即使文件在历史记录的任何一侧被重命名,也仅显示目标路径或最终路径。 使用 --combined-all-paths,显示每个父级中路径的名称,后跟合并提交中路径的名称。

-c--cc 的示例,没有 --combined-all-paths

::100644 100644 100644 fabadb8 cc95eb0 4866510 MM	desc.c
::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM	bar.sh
::100644 100644 100644 e07d6c5 9042e82 ee91881 RR	phooey.c

--combined-all-paths 添加到 -c--cc 时的示例

::100644 100644 100644 fabadb8 cc95eb0 4866510 MM	desc.c	desc.c	desc.c
::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM	foo.sh	bar.sh	bar.sh
::100644 100644 100644 e07d6c5 9042e82 ee91881 RR	fooey.c	fuey.c	phooey.c

请注意,*组合差异*仅列出从所有父级修改的文件。

使用 -p 生成补丁文本

使用 -p 选项运行 git-diff[1]git-log[1]git-show[1]git-diff-index[1]git-diff-tree[1]git-diff-files[1] 会生成补丁文本。 您可以通过 GIT_EXTERNAL_DIFFGIT_DIFF_OPTS 环境变量(请参阅 git[1])以及 diff 属性(请参阅 gitattributes[5])自定义补丁文本的创建。

-p 选项产生的稍微不同于传统的差异格式

  1. 它前面有一个“git diff”标头,如下所示

    diff --git a/file1 b/file2

    除非涉及重命名/复制,否则 a/b/ 文件名是相同的。 特别是,即使对于创建或删除,也不会使用 /dev/null 代替 a/b/ 文件名。

    当涉及重命名/复制时,file1file2 分别显示重命名/复制的源文件的名称以及重命名/复制产生的文件名。

  2. 它后面跟着一个或多个扩展的标头行

    旧模式 <mode> 新模式 <mode> 已删除文件模式 <mode> 新文件模式 <mode> 从 <path> 复制到 <path> 从 <path> 重命名到 <path> 相似性索引 <number> 相异性索引 <number> 索引 <hash>..<hash> <mode>

    文件模式 <mode> 以 6 位八进制数打印,包括文件类型和文件权限位。

    扩展标头中的路径名不包括 a/b/ 前缀。

    相似性索引是未更改行的百分比,相异性索引是已更改行的百分比。 它是向下舍入的整数,后跟一个百分号。 因此,100% 的相似性索引值保留给两个相等的文件,而 100% 的相异性意味着旧文件中没有一行进入新文件。

    索引行包括更改前后的 blob 对象名称。 如果文件模式没有改变,则包括 <mode>;否则,单独的行指示旧模式和新模式。

  3. 包含“不寻常”字符的路径名将按照配置变量 core.quotePath 的说明进行引用(请参阅 git-config[1])。

  4. 输出中的所有 file1 文件都引用提交之前的文件,而所有 file2 文件都引用提交之后的文件。 依次将每个更改应用于每个文件是不正确的。 例如,此补丁将交换 a 和 b

    diff --git a/a b/b
    rename from a
    rename to b
    diff --git a/b b/a
    rename from b
    rename to a
  5. Hunk 标头提及 hunk 应用于的函数的名称。 有关如何针对特定语言定制此内容的详细信息,请参阅 gitattributes[5] 中的“定义自定义 hunk 标头”。

组合差异格式

任何差异生成命令都可以使用 -c--cc 选项,在显示合并时生成*组合差异*。 这是使用 git-diff[1]git-show[1] 显示合并时的默认格式。 另请注意,您可以为任何这些命令提供合适的 --diff-merges 选项,以强制生成特定格式的差异。

“组合差异”格式如下所示

diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
	return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
  }

- static void describe(char *arg)
 -static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
  {
 +	unsigned char sha1[20];
 +	struct commit *cmit;
	struct commit_list *list;
	static int initialized = 0;
	struct commit_name *n;

 +	if (get_sha1(arg, sha1) < 0)
 +		usage(describe_usage);
 +	cmit = lookup_commit_reference(sha1);
 +	if (!cmit)
 +		usage(describe_usage);
 +
	if (!initialized) {
		initialized = 1;
		for_each_ref(get_name);
  1. 它前面有一个“git diff”标头,如下所示(当使用 -c 选项时)

    diff --combined file

    或如下所示(当使用 --cc 选项时)

    diff --cc file
  2. 它后面跟着一个或多个扩展的标头行(此示例显示具有两个父级的合并)

    索引 <hash>,<hash>..<hash> 模式 <mode>,<mode>..<mode> 新文件模式 <mode> 已删除文件模式 <mode>,<mode>

    mode <mode>,<mode>..<mode> 行仅在至少一个 <mode> 与其余 <mode> 不同时才会出现。 包含有关检测到的内容移动(重命名和复制检测)信息的扩展标头旨在与两个 *<tree-ish>* 的差异一起使用,并且不被组合差异格式使用。

  3. 它后面跟着一个双行的 from-file/to-file 标头

    --- a/file
    +++ b/file

    类似于传统的 *unified* 差异格式的双行标头,/dev/null 用于表示创建或删除的文件。

    但是,如果提供了 --combined-all-paths 选项,则您将获得一个 N+1 行 from-file/to-file 标头,而不是一个双行 from-file/to-file 标头,其中 N 是合并提交中父级的数量

    --- a/file
    --- a/file
    --- a/file
    +++ b/file

    如果重命名或复制检测处于活动状态,则此扩展格式可能很有用,以便您可以看到不同父级中文件的原始名称。

  4. Chunk 标头格式已修改,以防止人们意外地将其提供给 patch -p1。 创建组合差异格式是为了审查合并提交更改,而不是为了应用。 此更改类似于扩展的 *index* 标头中的更改

    @@@ <from-file-range> <from-file-range> <to-file-range> @@@

    在合并差异格式的块头中,@ 字符的数量是(父节点的数量 + 1)。

与传统的 统一 差异格式不同,后者显示两个文件 A 和 B,使用单列,列中带有 -(减号 — 出现在 A 中但在 B 中被删除)、+(加号 — 在 A 中缺失但在 B 中添加)或 " "(空格 — 未更改)前缀,此格式将两个或多个文件 file1、file2、…​ 与一个文件 X 进行比较,并显示 X 与每个 fileN 的不同之处。每个 fileN 对应一列,加在输出行的前面,以指示 X 的行与该 fileN 的不同之处。

列 N 中的 - 字符表示该行出现在 fileN 中,但未出现在结果中。列 N 中的 + 字符表示该行出现在结果中,并且 fileN 没有该行(换句话说,从该父节点的角度来看,该行被添加)。

在上面的示例输出中,函数签名从两个文件中都发生了更改(因此从 file1 和 file2 中都删除了两个 -,加上 ++ 表示添加的一行没有出现在 file1 或 file2 中)。此外,从 file1 开始,其他八行是相同的,但没有出现在 file2 中(因此以 + 为前缀)。

当通过 git diff-tree -c 显示时,它会将合并提交的父节点与合并结果进行比较(即 file1..fileN 是父节点)。当通过 git diff-files -c 显示时,它会将两个未解决的合并父节点与工作树文件进行比较(即 file1 是阶段 2,也就是“我们的版本”,file2 是阶段 3,也就是“他们的版本”)。

其他差异格式

--summary 选项描述了新添加、删除、重命名和复制的文件。--stat 选项将 diffstat(1) 图添加到输出中。这些选项可以与其他选项(例如 -p)组合使用,并且是为方便人类阅读而设计的。

当显示涉及重命名或复制的更改时,--stat 输出通过组合路径名的公共前缀和后缀来紧凑地格式化路径名。例如,将 arch/i386/Makefile 移动到 arch/x86/Makefile 并修改 4 行的更改将显示如下

arch/{i386 => x86}/Makefile    |   4 +--

--numstat 选项提供 diffstat(1) 信息,但专为方便机器读取而设计。--numstat 输出中的条目如下所示

1	2	README
3	1	arch/{i386 => x86}/Makefile

也就是说,从左到右

  1. 添加的行数;

  2. 一个制表符;

  3. 删除的行数;

  4. 一个制表符;

  5. 路径名(可能带有重命名/复制信息);

  6. 一个换行符。

-z 输出选项生效时,输出按以下方式格式化

1	2	README NUL
3	1	NUL arch/i386/Makefile NUL arch/x86/Makefile NUL

也就是说

  1. 添加的行数;

  2. 一个制表符;

  3. 删除的行数;

  4. 一个制表符;

  5. 一个 NUL(仅在重命名/复制时存在);

  6. preimage 中的路径名;

  7. 一个 NUL(仅在重命名/复制时存在);

  8. postimage 中的路径名(仅在重命名/复制时存在);

  9. 一个 NUL。

在重命名情况下,preimage 路径之前的额外 NUL 是为了允许读取输出的脚本判断当前正在读取的记录是单路径记录还是重命名/复制记录,而无需提前读取。在读取添加和删除的行后,读取到 NUL 将产生路径名,但如果那是 NUL,则该记录将显示两条路径。

GIT

git[1] 套件的一部分

scroll-to-top