简体中文 ▾ 主题 ▾ 最新版本 ▾ git-diff-tree 上次更新于 2.52.0

名称

git-diff-tree - 比较通过两个 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>…​]

描述

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

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

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

选项

-p
-u
--patch

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

-s
--no-patch

禁止 diff 引擎的所有输出。这对于像 git show 这样默认显示 patch 的命令很有用,可以抑制其输出,或者取消命令行中别名(alias)中像 --patch--stat 等选项的影响。

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

生成包含 <n> 行上下文(而不是通常的三行)的 diff。隐含 --patch

--output=<file>

输出到特定文件而不是标准输出。

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

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

--raw

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

--patch-with-raw

-p --raw 的同义词。

--indent-heuristic

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

--no-indent-heuristic

禁用缩进启发式算法。

--minimal

花费额外时间以确保生成最小的差异。

--patience

使用“patience diff”算法生成差异。

--histogram

使用“histogram diff”算法生成差异。

--anchored=<text>

使用“anchored diff”算法生成差异。

此选项可以多次指定。

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

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

选择一种差异算法。变体如下:

default
myers

基本的贪婪差异算法。目前,这是默认值。

minimal

花费额外时间以确保生成最小的差异。

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 会影响所有生成图形的命令,而设置 diff.statNameWidthdiff.statGraphWidth 不会影响 git format-patch。通过提供第三个参数 <count>,您可以将输出限制为前 <count> 行,如果还有更多行,则后跟 ...

这些参数也可以分别使用 --stat-width=<width>--stat-name-width=<name-width>--stat-count=<count> 进行设置。

--compact-summary

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

--numstat

类似于 --stat,但以十进制显示添加和删除的行数,并省略路径名缩写,以便更易于机器处理。对于二进制文件,输出两个 - 而不是说 0 0

--shortstat

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

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

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

changes

通过计算源文件中删除的行数或目标文件中添加的行数来计算 dirstat 数字。这会忽略纯代码移动 within a file 的量。换句话说,重新排列文件中的行不如其他更改计数多。这是未提供任何参数时的默认行为。

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

仅显示后像树中每个已更改文件的名称。文件名通常以 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。默认值为 diff.submoduleshort 格式(如果配置选项未设置)。

--color[=<when>]

显示彩色 diff。--color(即没有 =<when>)等同于 --color=always<when> 可以是 alwaysneverauto 之一。

--no-color

关闭彩色 diff。它与 --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

忽略行尾空格的更改。

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

使用一种特殊的基于行的格式,用于脚本消耗。添加/删除/未更改的运行以通常的统一 diff 格式打印,行首有一个 +/-/` ` 字符,并延伸到行尾。输入中的换行符用单独一行上的波浪号 ~ 表示。

none

再次禁用单词 diff。

请注意,尽管第一个模式的名称如此,如果启用,所有模式都使用颜色高亮显示更改的部分。

--word-diff-regex=<regex>

使用 <regex> 来决定什么是单词,而不是将非空白字符的连续序列视为一个单词。除非已启用,否则这也隐含 --word-diff

<regex> 的每个非重叠匹配都被视为一个单词。这些匹配之间的任何内容都被视为空格并被忽略(!) 以用于查找差异。你可能希望在正则表达式后追加 |[^[:space:]] 以确保它匹配所有非空格字符。包含换行符的匹配会被静默截断(!) 在换行符处。

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

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

--color-words[=<regex>]

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

--no-renames

关闭重命名检测,即使配置文件默认开启。

--rename-empty
--no-rename-empty

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

--check

当引入冲突标记或空格错误时发出警告。空格错误被认为是受 core.whitespace 配置控制的。默认情况下,行尾的空格(包括仅由空格组成的行)以及行开头缩进中紧跟在制表符后面的空格字符被视为空格错误。如果发现问题,退出状态将非零。与 --exit-code 不兼容。

--ws-error-highlight=<kind>

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

--full-index

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

--binary

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

--abbrev[=<n>]

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

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

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

它影响了将文件完全重写(rewrite)的更改的处理方式,而不是将其视为一系列删除和插入,其中只有少量文本碰巧与上下文匹配。它将其视为一次性的全部删除后一次性的全部插入,并且数字<m>控制 -B 选项的这一方面(默认为 60%)。-B/70% 指定,如果结果中保留的原始部分少于 30%,Git 将认为这是一次完全重写(即,否则生成的 patch 将是一系列删除和插入,并带有上下文行)。

当与 -M 一起使用时,完全重写的文件也被视为重命名(rename)的源头(通常 -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 选项仅在复制的原始文件在同一更改集(changeset)中被修改时才查找复制。此标志使命令检查未修改的文件作为复制源的候选。对于大型项目,这是一项非常耗时的操作,因此请谨慎使用。给出多个 -C 选项具有相同的效果。

-D
--irreversible-delete

省略删除的原始文件(preimage),即只打印标头,而不打印原始文件与 /dev/null 之间的差异。生成的补丁不适用于 patchgit apply;这仅适用于那些只想专注于查看更改后文本的人。此外,输出显然缺乏足够的信息来手动甚至手动反向应用此类补丁,因此得名于该选项。

-B 一起使用时,也会省略删除/创建对的删除部分中的原始图像。

-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 会排除已添加和已删除的路径。

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

-S<string>

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

当您正在寻找一段确切的代码(如结构体)并想了解该代码块自首次出现以来的历史记录时,这很有用:迭代地使用该功能将感兴趣的代码块从原始文件中反馈到 -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> 之前的(即 *skip to*)文件,或将它们移至输出末尾(即 *rotate to*)。这些选项主要用于 git difftool 命令,可能在其他情况下不太有用。

-R

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

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

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

-a
--text

将所有文件视为文本。

--ignore-cr-at-eol

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

--ignore-space-at-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 辅助程序(其退出代码不受信任)的执行,即其相应的配置选项 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] 或 diff 管道命令启用。

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

在生成 diff 时忽略对子模块的更改。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 恢复。这两个选项都是实验性的,未来可能会被删除。

--max-depth=<depth>

对于命令行上给出的每个路径说明符,最多向下递归 <depth> 层目录。值为 -1 表示无限制。不能与路径说明符中的通配符组合使用。给定一个包含 foo/bar/baz 的树,以下列表显示了每个选项集生成的匹配项

  • --max-depth=0 -- foo: foo

  • --max-depth=1 -- foo: foo/bar

  • --max-depth=1 -- foo/bar: foo/bar/baz

  • --max-depth=1 -- foo foo/bar: foo/bar/baz

  • --max-depth=2 -- foo: foo/bar/baz

如果没有给出路径说明符,则深度测量方式就好像所有顶级条目都被指定一样。请注意,这与从根开始测量不同,因为 --max-depth=0 仍将返回 foo。这允许您在要求顶级条目子集的同时仍然限制深度。

请注意,此选项仅支持树对象之间的差异,不支持与索引或工作树的差异。

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

<tree-ish>

tree 对象的 ID。

<path>…​

如果提供了此选项,则结果将限制为匹配提供的任何路径名模式的文件子集。

-r

递归进入子树。

-t

显示 tree 条目本身以及子树。隐含 -r。

--root

当指定 --root 时,初始提交将显示为一个大的创建事件。这等同于与 NULL tree 进行 diff。

--merge-base

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

--stdin

当指定 --stdin 时,该命令不会从命令行获取 <tree-ish> 参数。相反,它从标准输入读取包含以下内容的行:两个 <tree>,一个 <commit>,或一系列 <commit>。(使用单个空格作为分隔符。)

当给出两个 tree 时,它比较第一个 tree 和第二个 tree。当给出单个提交时,它比较该提交与其父提交。其余的提交(如果给出)被视为第一个提交的父提交。

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

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

-m

默认情况下,git diff-tree --stdin 不显示合并提交的差异。使用此标志,它会同时显示该提交与其所有父提交之间的差异,而不是一次显示一个父提交与结果之间的成对 diff(这是 -m 选项所做的)。此外,它只列出从所有父提交中修改过的文件。

-s

默认情况下,git diff-tree --stdin 显示差异,要么以机器可读格式(没有 -p),要么以 patch 格式(有 -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>` 一样。

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

注意
您可以指定存储库配置中的默认漂亮格式(请参阅 git-config[1])。
--abbrev-commit

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

这应该能让使用 80 列终端的人更容易阅读 `--pretty=oneline`。

--no-abbrev-commit

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

--oneline

这是 `--pretty=oneline --abbrev-commit` 的简写。

--encoding=<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])注解的提交。这是 `git log`、`git show` 和 `git whatchanged` 命令的默认行为,当命令行上没有给出 `--pretty`、`--format` 或 `--oneline` 选项时。

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

使用可选的 <ref> 参数,使用该 ref 来查找要显示的注释。当 ref 以 `refs/notes/` 开头时,它可以指定完整的 refname;当它以 `notes/` 开头时,`refs/` 和其他情况会加上 `refs/notes/` 前缀来形成 ref 的完整名称。

可以组合多个 `--notes` 选项来控制显示哪些注释。示例:“`--notes=foo`”将仅显示来自 `refs/notes/foo` 的注释;“`--notes=foo --notes`”将显示来自“refs/notes/foo”和默认 notes ref(s) 的注释。

--no-notes

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

--show-notes-by-default

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

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

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

--show-signature

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

--no-commit-id

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

-c

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

--cc

此标志会以类似于 -c 选项的方式改变合并提交 patch 的显示方式。它隐含了 -c-p 选项,并通过省略不相关的 hunks(其内容在父提交中只有两种变体,并且合并结果未修改地选择了其中一种)来进一步压缩 patch 输出。当所有 hunks 都不相关时,提交本身和提交日志消息将不会显示,就像任何其他“空 diff”情况一样。

--combined-all-paths

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

--always

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

美观格式 (PRETTY FORMATS)

如果该提交是合并提交,并且美化格式不是 `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 选项,否则日期格式为 --date=short。与任何带有格式占位符的 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* 信息显示真实的父提交,而不考虑 graft 或历史简化。请注意,此格式会影响提交的显示方式,但不会影响 diff 的显示方式,例如使用 git log --raw。要在原始 diff 格式中获取完整的对象名称,请使用 --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(<spec>)

      color specification, as described under Values in the "CONFIGURATION FILE" section of git-config[1]. By default, colors are shown only when enabled for log output (by color.diff, color.ui, or --color, and respecting the auto settings of the former if we are going to a terminal). %C(auto,<spec>) is accepted as a historical synonym for the default (e.g., %C(auto,red)). Specifying %C(always,<spec>) will show the colors even when color is not otherwise enabled (though consider just using --color=always to enable color for the whole output, including this format and anything else git might color). auto alone (i.e. %C(auto)) will turn on auto coloring on the next placeholders until the color is switched again.

      %m

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

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

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

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

      使下一个占位符至少占用 N 列宽度,如果需要,则在右侧填充空格。如果输出超过 N 列,则可以选择在左侧(ltrunc)截断(使用省略号 ..),在中间(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[:<option>,...])

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

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

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

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

      • pointer=<value>:显示在 HEAD 和它指向的分支之间(如果有)。默认为 " → "。

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

    例如,生成不带包裹或标签注释的装饰,并使用空格作为分隔符

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

    %(describe[:<option>,...])

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

    • tags[=<bool-value>]:而不是只考虑带注释的标签,也考虑轻量级标签。

    • abbrev=<number>:而不是使用默认的十六进制数字数量(这将根据存储库中的对象数量而变化,默认为 7),使用 <number> 位数字,或者根据需要使用的数字以形成唯一的对象名称。

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

    • exclude=<pattern>:不考虑匹配给定 glob(7) <pattern> 的标签,不包括 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

    引用日志身份名称

    %gN

    引用日志身份名称(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

    %ge

    引用日志身份电子邮件

    %gE

    引用日志身份电子邮件(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

    %gs

    引用日志主题

    %(trailers[:<option>,...])

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

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

    • only[=<bool>]:选择是否包含尾部块中的非尾部行。

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

    • unfold[=<bool>]:使其表现得好像给定了 interpret-trailer 的 --unfold 选项。例如,%(trailers:only,unfold=true) 会展开并显示所有尾部行。

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

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

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

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

布尔选项接受一个可选值 [=<bool-value>]。--type=bool git-config[1] 中的值,如 yes 和 off,都被接受。给出布尔选项而不带 =<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:“未知”更改类型(很可能是一个 bug,请报告)

状态字母 CR 后面总是跟着一个分数(表示移动或复制的源和目标之间的相似度百分比)。对于文件重写,状态字母 M 可能后面跟着一个分数(表示不相似度百分比)。

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

示例

:100644 100644 5be4a4a 0000000 M file.c

如果不使用 -z 选项,则具有“特殊”字符的路径名将像 core.quotePath 配置变量(参见 git-config[1])中解释的那样被引用。使用 -z 时,文件名将按原样输出,行以 NUL 字节结束。

合并的 diff 格式

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

  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

请注意,combined diff 仅列出从所有父级修改过的文件。

使用 -p 生成补丁文本

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

-p 选项生成的输出与传统的 diff 格式略有不同:

  1. 它前面是“git diff”头,看起来像这样:

    diff --git a/file1 b/file2

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

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

  2. 后面跟着一个或多个扩展头行:

    old mode <mode>
    new mode <mode>
    deleted file mode <mode>
    new file mode <mode>
    copy from <path>
    copy to <path>
    rename from <path>
    rename to <path>
    similarity index <number>
    dissimilarity index <number>
    index <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-header”。

组合 diff 格式

任何生成 diff 的命令都可以接受 -c--cc 选项,以便在显示合并时生成 *combined diff*。这是使用 git-diff[1]git-show[1] 显示合并时的默认格式。另请注意,您可以向这些命令中的任何一个提供适当的 --diff-merges 选项来强制以特定格式生成 diff。

“组合 diff”格式如下所示:

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. 后面跟着一个或多个扩展头行(此示例显示了一个包含两个父级的合并):

    index <hash>,<hash>..<hash>
    mode <mode>,<mode>..<mode>
    new file mode <mode>
    deleted file mode <mode>,<mode>

    当 <mode> 中至少有一个与其余不同的时,才会出现 mode <mode>,<mode>..<mode> 行。有关检测到的内容移动(重命名和复制检测)信息的扩展标头是为与两个 <tree-ish> 的 diff 设计的,并且不用于 combined diff 格式。

  3. 后面跟着一个两行的“源文件/目标文件”头:

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

    类似于传统 unified diff 格式的两行头,/dev/null 用于指示已创建或已删除的文件。

    然而,如果提供了 --combined-all-paths 选项,您将得到一个 N+1 行的“源文件/目标文件”头,而不是两行的“源文件/目标文件”头,其中 N 是合并提交中父级的数量:

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

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

  4. 块头格式已修改,以防止人们意外地将其馈送给 patch -p1。Combined diff 格式是为审查合并提交更改而创建的,不用于应用。更改类似于扩展的 index 标头中的更改。

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

    组合 diff 格式的块头中有(父级数量 + 1)个 @ 字符。

与传统的 *unified* diff 格式(显示两个文件 A 和 B,并带有一个单列,该列有 -(减号 — 出现在 A 中但从 B 中移除)、+(加号 — 在 A 中缺失但添加到 B 中),或 " "(空格 — 未更改)前缀)不同,此格式比较两个或多个文件 file1、file2、…… 和一个文件 X,并显示 X 与 fileN 的不同之处。文件 fileN 的数量加上每行输出中的一个列,用于指示 X 的行与该文件有何不同。

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

在上面的示例输出中,函数签名与两个文件都不同(因此从 file1 和 file2 都移除了两个 -,加上 ++ 表示一个添加到两个文件中都不存在的行)。此外,八行与 file1 相同,但未出现在 file2 中(因此前缀为 +)。

当由 git diff-tree -c 显示时,它比较合并提交的父级与合并结果(即 file1..fileN 是父级)。当由 git diff-files -c 显示时,它比较两个未解析的合并父级与工作树文件(即 file1 是阶段 2,也称为“我们的版本”,file2 是阶段 3,也称为“他们的版本”)。

其他 diff 格式

--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. 原始映像中的路径名;

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

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

  9. 一个 NUL。

在重命名的情况下,在原始文件路径之前的额外 NUL 字符是为了让读取输出的脚本能够区分当前读取的记录是单路径记录还是重命名/复制记录,而无需预读。在读取添加和删除行之后,读取到 NUL 将得到路径名,但如果它是 NUL,则记录将显示两个路径。

GIT

Git[1] 套件的一部分