Git 🌙
简体中文 ▾ Topics ▾ Latest version ▾ git-diff-tree last updated in 2.46.1

名称

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>] <目录树对象> [<目录树对象>] [<路径>…​]

描述

比较两个目录树对象中发现的 blob 的内容和模式。

如果只给出一个 <目录树对象>,则会将该提交与其父提交进行比较(见下文的 --stdin)。

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

选项

-p
-u
--patch

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

-s
--no-patch

抑制差异(diff)工具的所有输出。 对于默认显示补丁的 git show 等命令,可以压制其输出,或在别名中取消命令行中的 --patch--stat 等选项的效果。

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

生成带有 <n> 行上下文的差异,而不是通常的 3 行。暗含 --patch 选项。 暗含 --patch 选项。

--output=<文件>

输出到一个特定的文件,而不是标准输出。

--output-indicator-new=<字符>
--output-indicator-old=<字符>
--output-indicator-context=<字符>

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

--raw

生成原始格式的差异。 这是默认设置。

--patch-with-raw

-p--raw 的同义词。

--indent-heuristic

启用启发式的缩进区块的方法,使得补丁更易读。这是默认选项。

--no-indent-heuristic

禁用启发式缩进。

--minimal

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

--patience

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

--histogram

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

--anchored=<文本>

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

这个选项可以被指定多次。

如果某一个行同时存在于来源和目标中,各只出现一次,以这个文本开头,这个算法试图防止它在输出中以删除或添加的形式出现。它在内部使用了 "patience diff" 算法。

--diff-algorithm={patience|minimal|histogram|myers}

选择差异算法。有如下可选项:

default, myers

基本的贪婪差异算法。当前是默认设置。

minimal

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

patience

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

histogram

该算法将耐心算法扩展为 “支持低发生率的常见元素”。

例如,如果你将 diff.algorithm 变量配置为非默认值,但希望使用默认值,那么你必须使用 --diff-algorithm=default 选项。

--stat[=<宽度>[,<名称宽度>[,<数值>]]]

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

这些参数也可以用 --stat-width=<宽度>--stat-name-width=<名称宽度>--stat-count=<数量> 单独设置。

--compact-summary

在差异状态中输出扩展头信息的压缩摘要,如文件的创建或删除("new" 或 "good"。如果是符号链接,则为 "+l")和模式变化("+x" 或 "-x" 分别用于添加或删除可执行位)。这些信息被放在文件名部分和图形部分之间。暗含 --stat 选项。

--numstat

类似于 --stat,但是使用小数点和不含缩写的路径名显示添加和删除的行数,使其对程序更友好。对于二进制文件,输出两个 -,而不是 0 0

--shortstat

只输出使用 --stat 选项输出的最后一行,包含修改的文件总数,添加和删除的行数。

-X[<参数1,参数2,…​>]
--dirstat[=<参数1,参数2,…​>]

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

changes

通过计算从源文件中删除的行数或添加到目标文件中的行数来计算分布状态的数字。这忽略了文件内的代码移动行为。也就是说,在文件中重新排列的行不会像其他变化一样被计算在内。这是在没有给出参数时的默认行为。

lines

通过做常规基于行的差异分析,计算分布状态的数字,并将删除/添加的行数相加。(对于二进制文件,用 64 字节的块来计算,因为二进制文件没有行的概念)。在使用 --dirstat 时这个选项的行为开销比 changes 更大,但会对文件中重新排列的行进行计数。其得到的输出结果与其他的 --*stat 选项一致。

files

通过计算被改变的文件数量来计算分布状态的数字。在分布状态分析中,每一个被改变的文件都会被平等地计算。这是计算上开销最小的 --dirstat 行为,因为它无需查看文件内容。

cumulative

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

<limit>

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

例如:下面的参数会统计更改的文件,同时忽略占更改文件总数 10% 以下的目录,并累积父目录中的子目录计数:--dirstat=files,10,cumulative

--cumulative

--dirstat=cumulative 同义

--dirstat-by-file[=<参数1,参数2>…​]

与 --dirstat=files,<参数 1>,<参数 2> 同义

--summary

输出扩展头信息,如创建、重命名和模式变化等,的压缩摘要。

--patch-with-stat

同义词 -p --stat

-z

另外,当给出 --raw--numstat--name-only--name-status 选项时, 不合并路径名,并使用 NUL 作为输出字段终止符。

如果没有这个选项,带 “不常见” 字符的路径名会被引用,正如配置变量 core.quotePath 所解释的那样(参见 git-config[1])。

--name-only

Show only the name of each changed file in the post-image tree. The file names are often encoded in UTF-8. For more information see the discussion about encoding in the git-log[1] manual page.

--name-status

Show only the name(s) and status of each changed file. See the description of the --diff-filter option on what the status letters mean. Just like --name-only the file names are often encoded in UTF-8.

--submodule[=<格式>]

指定子模块中的差异如何显示。当指定 --submodule=short 选项时,会使用 short 格式。这种格式只显示范围的开头和结尾处的提交名称。当指定了 --submodule--submodule=log 时,会使用 log 格式。这种格式会像 git-submodule[1] summary 那样,列出该范围内的提交。当指定了 --submodule=diff 时,会使用 diff 格式。这个格式显示的是子模块内在提交范围之间的变化差异。默认为 diff.submodule,如果配置选项未设置, 则为 short 格式。

--color[=<when>]

显示有颜色的差异。--color(即不含 =<何时>)与 --color=always 相同。<何时> 可以是 alwaysneverauto

--no-color

关掉带彩色显示的差异。 这和 --color=never 相同。

--color-moved[=<模式>]

移动的代码行的颜色不同。 如果没有给出该选项,<模式> 默认为 no 如果没有给定模式选项,则为 zebra。 该模式必须以下其中之一:

no

被移动的行不突出显示。

default

zebra 的同义词。今后可能会改成更合理的模式。

plain

任何在某个位置被添加,且在另一个位置被删除的行,都会被用 color.diff.newMoved 着色。同样的,在差异中在某处删除且在其它地方添加的行会使用 color.diff.oldMoved 着色。这种模式可以读取任何被移动的行,但在代码审查中,它不能确定一个代码块是否未经排列而进行了移动。

blocks

使用贪心方法检测含至少 20 个字母数字字符的移动文本块。检测到的区块使用 color.diff.{old,new}Moved 的颜色。相邻的区块不能被区分开。

zebra

在 ‘块’ 模式下检测到移动的文本块。块使用 color.diff.{old,new}Moved 颜色或 color.diff.{old,new}MovedAlternative 颜色。这两种颜色之间的变化表示检测到了新的块。

dimmed-zebra

类似于 zebra 模式,但对使移动的代码中不关注的部分变暗。相邻两个区块的边界线被认为是重要,其余的部分是无关紧要的。dimmed_zebra 是一个被废弃的同义词。

--no-color-moved

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

--color-moved-ws=<模式>

这将配置在执行 --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[=<模式>]

显示词的差异,用 <模式> 来分隔已更改的词。默认情况下,单词是以空格分隔;请参考 --word-diff-regex。<模式> 默认为 plain,并且必须是以下其中之一:

color

只用颜色突出显示已更改的单词。暗含 --color 选项。

plain

显示更改的词为 [-removed-]{+added+}。如果在输入中出现定界符,则不尝试转义,所以输出可能是多义的。

porcelain

使用一种特殊的、基于行的格式,供脚本使用。添加/删除/未更改的运行数据以通常的统一的差异格式输出,行的开头以 + / - / ` ` 字符开始,一直到行的结尾。输入中的新行用单行上的 `~`表示。

none

再次禁用单词差异模式。

请注意,无论第一个模式的名称是什么,如果启用该选项,将在所有模式中使用颜色,以高亮显示更改的部分。

--word-diff-regex=<正则表达式>

使用 <正则表达式> 来确定单词的格式,而不是将一串非空白行视为单词。除非已启用,否则还暗含 --word-diff 选项。

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

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

正则表达式也可以通过差异程序或配置选项来设置,参见 gitattributes[5]git-config[1]。显式指明会覆盖任何程序或配置。差异程序会覆盖配置。

--color-words[=<正则表达式>]

--word-diff=color 和(如果指明了正则表达式)--word-diff-regex=<正则表达式> 两个选项含义相同。

--no-renames

关闭重命名检测,即使配置文件给出的默认是这样做。

--[no-]rename-empty

是否使用空的数据对象作为重命名源。

--check

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

--ws-error-highlight=<种类>

突出显示差异中 context(上下文)、old(旧)或 new(新)行中的空格错误。多个值用逗号隔开,none 选项会重置以前的值,default 重置列表为 newallold,new,context 的简写。当没有给定这个选项,并且配置变量 diff.wsErrorHighlight 没有设置时,只有 new 行中的空格错误会被高亮显示。空格错误会用 color.diff.whitespace 配置进行着色。

--full-index

在生成补丁格式输出时,在 index(索引)行上显示完整的图像前和图像后数据对象名称,而不仅是前几个字符。

--binary

除了 --full-index 输出的差异之外,输出二进制的差异。其可以用 git-apply 命令来应用。暗含 --patch 选项。 暗含 --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>]]

将完整的重写更改切分成删除和创建对(pair)。这有两个目的:

它会影响决定更改形式的阈值,当单个文件内修改总量达到一定值时,会认为该文件进行了完全重写,而不是将一系列删除和插入操作视为修改。如果视为多个删除和插入修改,修改中的行可能会碰巧在文本上与原文一致,从而被当作上下文。选项中的数字 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

删除时省略原内容,即只打印头信息,而不打原内容和 /dev/null 之间的差异。所产生的补丁并不是要用于 patchgit apply;这只是为了让人们只专注于审查修改后的文本。此外,输出结果显然缺乏足够的信息来反转,或手动应用这样一个补丁,因此这个选项的名称如此。

当与 -B 一起使用时,也省略删除/创建对中删除部分的原内容。

-l<数量>

-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>

寻找改变文件中指定字符串出现次数的差异(即增加/删除)。供脚本编写者使用。

当您正在寻找确切的代码块(如结构体),并且想知道该块自首次出现以来的历史记录时,这将非常有用:通过 -S 选项迭代,将原文件中的感兴趣的块显示出,并继续进行,直到获得该块的第一个版本。

二进制文件也会被搜索到。

-G<正则表达式>

查找其补丁文本包含与 <正则表达式> 匹配的添加/删除行的差异。

为了说明 -S<正则表达式> --pickaxe-regex-G<正则表达式> 之间的区别,假设某次提交在同一文件中有以下差异:

+    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=<对象ID>

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

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

--pickaxe-all

当使用 -S-G 选项找到一个更改时,显示该更改集中的所有更改,而不仅仅是显示包含 <string> 更改的文件。

--pickaxe-regex

-S 选项的 <string> 参数当作扩展的 POSIX 正则表达式来匹配。

-O<顺序控制文件>

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

输出顺序由 <顺序控制文件> 中的 glob 模式的顺序决定。所有路径名与第一个模式匹配的文件首先输出,路径名与第二个模式匹配(但不与第一个模式匹配)的文件其次输出,以此类推。所有路径名与任何模式匹配的文件会最后输出,就像在文件末尾有一个隐含的全部匹配模式。如果多个路径名具有相同的等级(它们匹配相同的模式,但没有匹配先前的模式),它们相对于彼此的输出顺序是正常的。

<顺序控制文件> 格式如下:

  • 空白行会被忽略,因此可以用它们作为分隔符,以保证可读性。

  • 以井号("#")开头的行会被忽略,所以它们可以用来做注释。如果模式以井号开头,则需要在模式的开头加上反斜杠("\")。

  • 每一行都包含一个模式。

模式的语法和语义与 fnmatch(3) 中使用的相同,不包括 FNM_PATHNAME 标志,但在删除路径名中结尾任意几个成分后匹配的情况下例外。例如,模式 "foo*bar" 匹配 "fooasdfbar" 和 "foo/bar/baz/asdf",但不匹配 "foobarx"。

--skip-to=<文件>
--rotate-to=<文件>

从输出中丢弃命名 <文件> 之前的文件(即 skip to),或将它们移到输出的末尾(即 rotate to)。 这些选项主要是为使用 git difftool 命令而发明的,在其他情况下可能用处不大。

-R

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

--relative[=<路径>]
--no-relative

当从项目的子目录中运行时,可以排除目录外的变化,并通过这个选项显示相对于它的路径名。当你不在子目录中时(例如在纯仓库中),你可以通过 <路径> 参数来指明要使输出相对于哪个子目录。--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<正则表达式>
--ignore-matching-lines=<正则表达式>

忽略所有行均匹配 <正则表达式> 的更改。 此选项可指定多次。

--inter-hunk-context=<行数>

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

-W
--function-context

在每个修改中的上下文行显示整个函数。函数名称的确定方式与 git diff 计算补丁头的方式相同(参见 gitattributes[5] 中的 自定义区块头 )。

--exit-code

让程序以类似 diff(1) 的代码退出。也就是说,如果有差异则返回1,否则返回0。

--quiet

禁用程序的所有输出。暗含 --exit-code 选项。禁用那些退出代码不被信任的外部差异辅助程序的执行,即它们的相应配置选项 diff.trustExitCodediff.<驱动程序>.trustExitCode 或环境变量 GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE 设置为 false。

--ext-diff

允许执行外部差异器。如果你用 gitattributes[5] 设置了一个外部差异驱动程序,你需要在 git-log[1] 和相关命令中使用这个选项。

--no-ext-diff

禁止使用外部差异器。

--textconv
--no-textconv

允许(或不允许)在比较二进制文件时运行外部文本转换过滤器。详情请参见 gitattributes[5] 。由于文本转换过滤器通常是单向转换,因此产生的差异适合人类用户使用,但不能应用(apply)。因此默认情况下,只有 git-diff[1]git-log[1] 启用文本转换过滤器,而 git-format-patch[1] 或 diff plumbing 命令则不启用。

--ignore-submodules[=<when>]

在生成差异时忽略子模块的修改。<when> 可以是 "none"、"untracked"、"dirty " 或 "all","all" 是默认选项。使用 "none" 会在子模块包含未跟踪或修改的文件,或者它的HEAD 与上级项目中记录的提交不同时,认为它被修改了,并且可以用来覆盖 git-config[1]gitmodules[5]忽略 选项的设置。当使用 "untracked" 时,当子模块只包含未跟踪的内容时,它们不会被认为是有改动的(但它们仍然会被扫描是否有被修改的内容)。使用 "dirty" 会忽略所有对子模块工作树的修改,只有存储在上级项目中的提交的修改才会被显示出来(这是在1.7.0之前的行为)。使用 "all" 会隐藏所有对子模块的修改。

--src-prefix=<前缀>

显示给定的源前缀而不是 "a/"。

--dst-prefix=<前缀>

显示给定的目标前缀,而不是“b/”。

--no-prefix

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

--default-prefix

Use the default source and destination prefixes ("a/" and "b/"). This overrides configuration variables such as diff.noprefix, diff.srcPrefix, diff.dstPrefix, and diff.mnemonicPrefix (see git-config(1)).

--line-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。

<路径>…​

如果提供了该选项,则结果仅限于与所提供的路径规格之一相匹配的文件子集。

-r

向子树递归。

-t

展示目录树本身以及子树。 暗指 -r。

--root

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

--merge-base

不要直接比较 <树对象>,而是使用两个 <树对象> 之间的合并基数作为 "before" 边。 必须有两个 <树对象>,而且必须都是提交。

--stdin

如果指定了 --stdin,命令不会从命令行获取 <树对象> 参数。 相反,它会从标准输入中读取包含两个 <目录树>、一个 <提交> 或一个 <提交> 列表的行。 (使用单空格作为分隔符)

当给出两个树时,它会比较第一个目录树和第二个目录树。 如果给出的是单个提交,则会将该提交与其父提交进行比较。 如果给出了其余的提交,则会把它们当作第一个提交的父提交来使用。

比较两棵目录树时,会在差值前打印两棵目录树的 ID(用空格分隔并以换行结束)。 比较提交时,则会打印第一个(或唯一一个)提交的 ID,并以换行结束。

以下标记会进一步影响比较提交(而不是目录树树)时的行为。

-m

默认情况下,git diff-tree --stdin 不会显示合并提交的差异。 有了这个标记,它就会显示该提交与其所有父提交的差异。另请参阅 -c

-s

默认情况下,git diff-tree --stdin 会以机器可读形式(不含 -p)或补丁形式(含 -p)显示差异。 该输出可以被抑制。 只有使用 -v 标志时才有用。

-v

该标记会使 git diff-tree --stdin 在差异之前显示提交信息。

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

以指定的格式打印提交日志的内容,其中'<format>'可以是’oneline'、shortmediumfullfullerreferenceemailrawformat:<string>'和’tformat:<string>'之一。 当<format>'不是上述任何一种,并且其中有'%placeholder’时,它的作用就像给出'--pretty=tformat:<format>'一样。

参见 "PRETTY FORMATS "部分,了解每种格式的一些额外细节。 当'=<格式>'部分被省略时,它默认为’中等'。

注意:你可以在版本库配置中指定默认的漂亮格式(见git-config[1])。

--abbrev-commit

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

这应该使"--pretty=oneline "对于使用80列终端的人来说更容易阅读。

--no-abbrev-commit

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

--oneline

这是"--pretty=oneline --abbrev-commit "的简写,一起使用。

--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个空格(即 "中",这是默认的,"全",和 "更全")。

--notes[=<引用>]

在显示提交日志信息时,显示注释提交的说明(见git-notes[1])。 这是`git log`、git show`和`git whatchanged`命令的默认设置,当命令行中没有给出--pretty`、--format`或--oneline`选项时。

默认情况下,显示的注释来自于`core.notesRef`和`notes.displayRef`变量(或相应的环境覆盖)中列出的注释参考。更多细节见git-config[1]

有了一个可选的 <引用> 参数,就可以使用引用来寻找要显示的笔记。 当引用以 refs/notes/ 开头时,可以指定完整的引用名称;当它以 notes/ 开头时, refs/ ,否则 refs/notes/ 前缀,形成引用的全名。

多个—​音符选项可以组合起来,控制哪些音符被显示。例如。"--notes=foo "将只显示来自 "refs/notes/foo "的注释;"--notes=foo --notes "将同时显示来自 "refs/notes/foo "和默认注释的注释。

--no-notes

不显示注释。这否定了上面的`--notes`选项,因为它重新设置了显示注释的注释列表。 选项按照命令行给出的顺序进行解析,因此,例如"--notes --notes=foo --no-notes --notes=bar "将只显示来自 "refs/notes/bar "的注释。

--show-notes-by-default

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

--show-notes[=<引用>]
--[no-]standard-notes

这些选项已被废弃。请使用上面的 --notes/--no-notes 选项来代替。

--show-signature

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

--no-commit-id

git diff-tree outputs a line with the commit ID when applicable. This flag suppresses the commit ID output.

-c

这个标记改变了合并提交的显示方式(这意味着它只在命令为一个 <树对象> 或 --stdin 时有用)。 它会同时显示每个父文件与合并结果之间的差异,而不是一次一个地显示父文件与合并结果之间的成对差异(-m 选项就是这么做的)。 此外,它只列出从所有父文件修改过的文件。

--cc

这个标记改变了合并提交补丁的显示方式,与 -c 选项类似。它暗示了 -c-p 选项,并通过省略不感兴趣的 hunk 来进一步压缩补丁输出,这些 hunk 的内容在父节点中只有两种变体,合并结果会选择其中之一而不做修改。 如果所有 hunk 都是无趣的,提交本身和提交日志信息都不会显示,就像其他 “空差异” 情况一样。

--combined-all-paths

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

--always

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

漂亮的格式

如果提交是一个合并,并且如果pretty-format不是 "oneline"、"email "或 "raw",那么在 "Author: "一行之前会插入一个附加行。 这一行的开头是 "Merge:这一行以 "Merge: "开头,并打印出祖先提交的哈希值,用空格分隔。 请注意,如果你限制了你的历史视图,那么列出的提交不一定是*直接*父级提交的列表:例如,如果你只对与某个目录或文件有关的修改感兴趣。

有几种内置的格式,你可以通过将 pretty.<名称> 配置选项设置为另一种格式名称或 format: 字符串来定义额外的格式,如下所述(见 git-config[1] )。下面是内置格式的细节:

  • oneline

    <哈希值> <标题行>

    这个设计是为了尽可能的紧凑。

  • short

    承诺<hash>
    作者。<作者>的情况
    <标题行>
  • medium

    commit <哈希值>
    Author: <作者>
    Date:   <提交日期>
    <标题行>
    <完整的提交信息
  • full

    承诺<hash>
    作者。< Author>
    承诺。<committer>(提交者)。
    <标题行>
    <完整的提交信息
  • fuller

    commit <哈希值>
    Author:     <作者>
    AuthorDate: <作者提交日期>
    Commit:     <提交者>
    CommitDate: <提交者提交日期>
    <标题行>
    <完整的提交信息
  • ‘引用’

    <缩写哈希值>(<标题行>,<简短的作者日期>)

    这种格式用于在提交信息中引用另一个提交,与`--pretty='format:%C(auto)%h (%s, %ad)'相同。 默认情况下,日期的格式为`--date=short`,除非明确指定其他`--date`选项。 与任何带有格式占位符的`format:一样,其输出不受其他选项的影响,如--decorate`和`--walk-reflogs`。

  • email

    From <哈希> <日期>
    From: <作者>
    Date: <作者提交日期>
    Subject: [PATCH] <标题行>
    <完整的提交信息
  • mboxrd

    和 "email "一样,但提交信息中以 "From "开头的行(前面有零个或多个">")用">"引出,这样就不会被混淆为开始了一个新的提交。

  • raw

    原始 "格式显示的是整个提交对象中存储的内容。 值得注意的是,无论是否使用了 --abbrev 或 --no-abbrev,哈希值都会被完整地显示出来,而’parent’信息会显示真正的父级提交,不会考虑移花接木或历史简化。注意,这种格式会影响提交的显示方式,但不会影响diff的显示方式,比如用`git log --raw`来显示。要获得原始差异格式的完整对象名称,请使用`--no-abbrev`。

  • format:<格式字符串>

    format:<格式字符串 格式允许你指定要显示的信息。它的工作原理有点像 printf 格式,但有一个明显的例外,那就是换行符是 %n 而不是 \n

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

    fe6e0ee的作者是Junio C Hamano, 23小时前
    标题是 >>t4119: 测试传统diff输入的自动计算-p<n>。

    占位符是:

    • 占位符,可扩展为一个字面字符:

      %n

      换行

      %%

      一个原始的'%'

      %x00

      %x 后跟两个十六进制数字,会被一个包含十六进制数字值的字节替换(在本文档的其余部分,我们称之为 “字面格式化代码”)。

    • 影响后面占位符的格式化的占位符:

      %Cred

      切换颜色为红色

      %Cgreen

      切换颜色为绿色

      %Cblue

      将颜色改为蓝色

      %Creset

      重置颜色

      %C(…​)

      颜色规范,如git-config[1]的 "配置文件 "部分中的数值描述。 默认情况下,只有在启用日志输出时才会显示颜色(通过 color.diff, color.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

      尊重 .mailmap 作者的本地部分(参见 %al ),参见 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

      ref名称,就像git-log[1]的—​decorate选项。

      %D

      没有"("、")"包装的参考文献名称。

      %(decorate[:<选项>])

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

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

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

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

      • point=<值>: 显示在 HEAD 和其指向的分支(如果有)之间。 默认为 " -> "。

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

    例如,制作不带包装或标签注释的装饰,并用空格作为分隔符:

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

    %(describe[:<选项>])

    人类可读的名字,像git-describe[1];空字符串表示不可描述的提交。 `describe`字符串后面可以有冒号和零个或多个逗号分隔的选项。 当标签同时被添加或删除时,描述可能不一致。

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

    • abbrev=<数量>:不使用缩写对象名称的默认十六进制位数(根据仓库中对象的数量而变化,默认为 7 位),而是使用 <数量> 的位数,或根据需要的位数来组成唯一的对象名称。

    • 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分钟前};其格式遵循`-g`选项的规则。@'前面的部分是命令行上给出的参考文献名称(所以`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[:<选项>])

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

    • key=<键>:只显示具有指定密钥的为主。匹配是不分大小写的,后面的冒号是可选的。如果多次给出选项,则显示与任何键匹配的为主行。该选项自动启用 only 选项,使拖车块中的非尾注行被隐藏。如果不希望这样,可以用 only=false 禁用。 例如,%(trailers:key=Reviewed-by) 显示键为 Reviewed-by 的拖车行。

    • only[=<布尔值>] :选择是否应该包括来自尾注块的非尾注行。

    • separator=<sep>: specify the separator inserted between trailer lines. Defaults to a line feed character. The string <sep> may contain the literal formatting codes described above. To use comma as separator one must use %x2C as it would otherwise be parsed as next option. E.g., %(trailers:key=Ticket,separator=%x2C ) shows all trailer lines whose key is "Ticket" separated by a comma and a space.

    • unfold[=<布尔值>]:使它的行为就像 interpret-trailer 的 --unfold 选项被给出一样。例如,`%(trailers:only,unfold=true)`会展开并显示所有的尾注行。

    • keyonly[=<布尔值>]:只显示尾注的关键部分。

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

    • key_value_separator=<sep>: specify the separator inserted between the key and value of each trailer. Defaults to ": ". Otherwise it shares the same semantics as separator=<sep> above.

Note
一些占位符可能取决于给修订版遍历引擎的其他选项。例如,%g* reflog选项将插入一个空字符串,除非我们正在遍历reflog条目(例如,通过`git log -g`)。%d`和%D`占位符将使用 "短 "装饰格式,如果`--decorate`没有在命令行上提供。

布尔选项接受一个可选的值`[=<布尔值>]。`true, false, on, `off`等值都可以接受。参见git-config[1]中 “示例” 的 “布尔” 子章节。如果一个布尔选项没有给出值,它就被启用。

如果你在占位符的'%后面加了一个`+(加号),当且仅当占位符扩展为一个非空字符串时,在扩展前会立即插入换行符。

如果你在占位符的'%后面加了一个`-(减号),如果且仅当占位符扩展为空字符串时,紧接着扩展前的所有连续换行将被删除。

如果你在占位符的'%'后面加了一个``(空格),当且仅当占位符扩展到一个非空字符串时,空格就会紧接着插入扩展。

  • t格式:

    tformat: 格式的工作原理与 format: 完全一样,只是它提供了 “终止符” 语义,而不是 “分隔符” 语义。换句话说,每个提交都附加了信息结束符(通常是换行符),而不是在条目之间放置一个分隔符。 这意味着单行格式的最后一个条目将正确地以新行结束,就像 “单行” 格式那样。 比如说:

    $ 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-index","git-diff-tree","git-diff-files" 和 "git diff --raw" 的原始输出格式非常相似。

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

git-diff-index <目录树对象>

比较 <目录树对象> 和文件系统上的文件。

git-diff-index --cached <目录树对象>

比较 <目录树对象> 和索引。

git-diff-tree [-r] <目录树对象 1> <目录树对象 2> [<模式>…​]

比较由两个参数传递的目录树。

git-diff-files [<模式>…​]

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

"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. sha1 表示 "dst"(目标文件);0{40} 表示删除、未合并或 “工作目录树与索引不同步”。

  9. 空格。

  10. 状态,在可选值 "score" 之后。

  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:"unknown"(未知)更改类型(可能为错误,请报告)

状态字母 C 和 R 后面总是一个分数(表示移动或复制的源与目标之间的相似性百分比)。状态字母 M 后面可能有文件重写的分数(表示相异百分比)。

如果文件是文件系统上的新文件,并且与索引不同步,则 <sha1> 将显示为全 0。

例如:

:100644 100644 5be4a4a 0000000 M file.c

如果没有 -z 选项,带 “不常见” 字符的路径名会被加上引号,正如配置变量 core.quotePath 所解释的那样(参见 git-config[1])。 使用 -z 选项,文件名将被逐字输出,并以 NUL 字节结束。

合并的差异格式

"git-diff-tree"、"git-diff-files" 和 "git-diff --raw" 可以使用 -c--cc 选项来生成差异输出,也可以用于合并提交。其输出与上面描述的格式有以下不同:

  1. 每个父提交都有一个冒号

  2. 有更多的 "src" 文件模式和 "src" sha1

  3. 状态是每个父提交的状态字符的合并

  4. 无可选的分数("score")数字

  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 生成补丁文本

使用 -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. 它的后面是一个或多个扩展头信息行:

    old mode <模式>
    new mode <模式>
    deleted file mode <模式>
    new file mode <模式>
    copy from <路径>
    copy to <路径>
    rename from <路径>
    rename to <路径>
    similarity index <数字>
    dissimilarity index <数字>
    index <哈希>..<哈希> <模式>

    文件模式被打印为 6 位八进制数字,包括文件类型和文件权限位。

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

    相似性指数是未改变的行占比,而不相似性指数是改变的行占比。它是四舍五入的整数,后有百分号。因此,100%的相似度指数指为两个文件相等,而 100% 的不相似度意味着入新文件中没有旧文件中的行。

    索引行包括改变前和改变后的 blob 对象名称。如果文件模式没有变化,则包含 <模式>;否则,分别显示新旧模式。

  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. 块头提到了块头所适用的函数的名称。 参见 gitattributes[5] 中的 “定义自定义 hunk-header”,以了解如何针对特定语言进行定制。

合并的差异格式

任何生成差异的命令都可以使用 -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. 它的后面是一个或多个扩展头信息行(本例显示的是与两个父提交的合并):

    index <哈希>,<哈希>..<哈希>
    mode <模式>,<模式>..<模式>
    new file mode <模式>
    deleted file mode <模式>,<模式>

    mode<模式>,<模式>..<模式> 行仅在 <模式> 中至少有一个与其余的不同时才会出现。包含有关检测到的内容移动的信息 (重命名和复制检测) 的扩展标头设计为使用两个 <目录树对象> 的 diff,不能用于组合的 diff 格式。

  3. 它的后面是两行源文件/目标文件的头信息:

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

    与传统 ‘统一’ diff 格式的双行标题类似,/dev/null 用于表示已创建或已删除的文件。

    但是,如果提供了 --combined-all-paths 选项,你就会得到一个 N+1 行的源文件/目标文件头,其中 N 是合并提交中的父提交数量:

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

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

  4. 修改了文件块头信息的格式,以防止不小心将其送入 patch -p1。合并的差异格式是为审查合并提交的修改而创建的,并不是为了应用。这个变化类似于扩展的 "索引" 头信息的变化:

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

    块中有(父提交数量+1)@ 字符,用于合并的差异格式。

与传统的 "统一" 差异格式不同,这种格式显示两个文件 A 和 B 的列,其中有 -(减号 — 在 A 中出现,但在 B 中删除),+(加号 — 在 A 中缺少,但在 B 中增加),或 " "(空格 — 不变)前缀,这种格式比较两个或多个文件与一个文件 X,并显示 X 与其中每个文件的差异。文件中的每一个都有一列被前置在输出行中,以指出 X 的行与它的不同之处。

第 N 列中的 - 字符意味着该行出现在文件 N 中,但它没有出现在结果文件中。第 N 列中的 + 字符意味着该行出现在结果文件中,而文件 N 中没有该行(换句话说,从该父提交的角度来看,该行是被添加的)。

在上面的输出示例中,两个文件中的函数签名都被改变了(因此从文件 1 和文件 2 中都有表示删除的 -,而 ++ 表示被添加的一行没有出现在文件 1 或文件 2 中)。另外还有 8 行与文件 1 中的相同,但没有出现在文件 2 中(因此前缀为 +)。

当用 git diff-tree -c 显示时,它将合并提交的父提交文件与合并结果进行比较(即文件 1 …​ 文件 N 是父提交文件)。当用 git diff-files -c 显示时,它将两个未解决的合并父提交文件与工作树文件进行比较(即文件 1 是阶段 2 ,又称 "我们的版本",文件 2 是阶段 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. 完整路径名;

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

  8. 完整路径名(仅在重命名/复制时存在);

  9. 一个 NUL 字符。

在重命名的情况下,完整路径前多出的 NUL 为了让读取输出的脚本能够判断,当前被读取的记录是单路径记录还是重命名/复制记录,而不需要提前读取。在读完增删行数后,读至 NUL 会得到路径名,但如果先读到 NUL,记录将显示两个路径。

GIT

属于 git[1] 文档

scroll-to-top