Skip to content

git-diff

显示提交之间的更改、提交与工作树之间的更改等

概要

bash
git diff [<options>] [<commit>] [--] [<path>...]
git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]
git diff [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...]
git diff [<options>] <commit>...<commit> [--] [<path>...]
git diff [<options>] <blob> <blob>
git diff [<options>] --no-index [--] <path> <path> [<pathspec>...]

描述

显示工作树与索引或树之间的更改、索引与树之间的更改、两棵树之间的更改、合并产生的更改、两个 blob 对象之间的更改,或磁盘上两个文件之间的更改。

git diff [<options>] [--] [<path>...]::

此形式用于查看您相对于索引(下次提交的暂存区)所做的更改。
换句话说,这些差异是您_可以_告诉 Git 进一步添加到索引但尚未添加的内容。
您可以使用 [git-add(1)](/commands/git-add) 来暂存这些更改。

git diff [<options>] --no-index [--] <path> <path> [<pathspec>...]::

此形式用于比较文件系统上给定的两个路径。
在 Git 控制的工作树中运行命令且至少有一个路径指向工作树外部时,
或在 Git 控制的工作树之外运行命令时,可以省略 `--no-index` 选项。
此形式隐含 `--exit-code`。如果两个路径都指向目录,
则可以提供额外的路径规格。这些将限制包含在差异中的文件。
所有此类路径规格必须是相对的,因为它们应用于差异的两侧。

git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]::

此形式用于查看您相对于指定的 _&lt;commit&gt;_ 暂存的更改。
通常您会希望与最新的提交进行比较,因此如果不指定 _&lt;commit&gt;_,
则默认为 `HEAD`。
如果 `HEAD` 不存在(例如未诞生的分支)且未指定 _&lt;commit&gt;_,
则显示所有已暂存的更改。`--staged` 是 `--cached` 的同义词。

如果指定了 --merge-base,则使用 <commit>HEAD 的合并基础 而不是使用 <commit>git diff --cached --merge-base A 等同于 git diff --cached $(git merge-base A HEAD)

git diff [<options>] [--merge-base] <commit> [--] [<path>...]::

此形式用于查看您工作树中相对于指定的 _&lt;commit&gt;_ 的更改。
您可以使用 `HEAD` 与最新的提交进行比较,
或使用分支名称与不同分支的顶端进行比较。

如果指定了 --merge-base,则使用 <commit>HEAD 的合并基础 而不是使用 <commit>git diff --merge-base A 等同于 git diff $(git merge-base A HEAD)

git diff [<options>] [--merge-base] <commit> <commit> [--] [<path>...]::

此形式用于查看两个任意 _&lt;commit&gt;_ 之间的更改。

如果指定了 --merge-base,则使用两个提交的合并基础作为"之前"一侧。 git diff --merge-base A B 等同于 git diff $(git merge-base A B) B

git diff [<options>] <commit> <commit>...<commit> [--] [<path>...]::

此形式用于查看合并的结果。第一个列出的 _&lt;commit&gt;_ 必须是合并本身;
其余两个或更多提交应该是其父提交。生成所需修订集的便捷方式是使用
后缀 `@` 和 `^!`。如果 `A` 是一个合并提交,
则 `git diff A A^@`、`git diff A^!` 和 `git show A` 都会给出相同的组合差异。

git diff [<options>] <commit>..<commit> [--] [<path>...]::

此形式与前面的形式(不带 `..`)同义,用于查看两个任意 _&lt;commit&gt;_ 之间的更改。
如果省略一侧的 _&lt;commit&gt;_,则效果与使用 `HEAD` 相同。

git diff [<options>] <commit>...<commit> [--] [<path>...]::

此形式用于查看包含并直到第二个 _&lt;commit&gt;_ 的分支上的更改,
从两个 _&lt;commit&gt;_ 的共同祖先开始。`git diff A...B` 等同于
`git diff $(git merge-base A B) B`。您可以省略任何一个 _&lt;commit&gt;_,
这与使用 `HEAD` 效果相同。

以防您正在进行一些特殊操作,需要注意的是,上述描述中除了 --merge-base 情况 和使用 .. 表示法的最后两种形式外,所有 <commit> 都可以是任何 <tree>。 一个值得关注的树是由名为 AUTO_MERGE 的引用指向的树, 该引用由 ort 合并策略在遇到合并冲突时写入(参见 git-merge(1))。 将工作树与 AUTO_MERGE 进行比较可以显示您迄今为止为解决文本冲突所做的更改 (参见下面的示例)。

有关 <commit> 表示方式的更完整列表, 请参阅 gitrevisions(7) 中的"指定修订"部分。 但是,diff 是关于比较两个_端点_,而不是范围, 范围表示法(<commit>..<commit><commit>...<commit>) 并不意味着 gitrevisions(7) 中"指定范围"部分所定义的范围。

git diff [<options>] <blob> <blob>::

此形式用于查看两个 blob 对象原始内容之间的差异。

选项

-p

-u

--patch

生成补丁(参见 <<generate_patch_text_with_p>>)。 ifdef::git-diff[] 这是默认行为。 endif::git-diff[]

-s

--no-patch

抑制差异机制的所有输出。对于默认显示补丁的命令(如 git show) 来说很有用,可以消除其输出, 或者用于取消命令行中较早出现的 --patch--stat 等选项的效果。

endif::git-format-patch[]

ifdef::git-log[]

-m

以默认格式显示合并提交的差异。这类似于 --diff-merges=on, 但除非同时给出 -p,否则 -m 不会产生输出。

-c

为合并提交生成组合差异输出。 --diff-merges=combined -p 的快捷方式。

--cc

为合并提交生成密集组合差异输出。 --diff-merges=dense-combined -p 的快捷方式。

--dd

对合并提交和常规提交都生成相对于第一个父提交的差异。 --diff-merges=first-parent -p 的快捷方式。

--remerge-diff

为合并提交生成重新合并差异输出。 --diff-merges=remerge -p 的快捷方式。

--no-diff-merges

--diff-merges=off 的同义词。

--diff-merges=<format>

指定用于合并提交的差异格式。默认为 {diff-merges-default}, 除非使用了 --first-parent,此时默认为 first-parent。 + 支持以下格式:

示例

检查工作树的各种方式::

+

default;; myers;; 基本的贪心差异算法。目前这是默认算法。 minimal;; 花费额外时间以确保产生尽可能小的差异。 patience;; 在生成补丁时使用"耐心差异"算法。 histogram;; 此算法扩展了耐心算法以"支持

低出现率的公共元素"。

使用此选项时输出的内容可能会发生变化, 其与其他选项的交互也可能会变化(除非有明确文档说明)。

--combined-all-paths:: 使组合差异(用于合并提交)列出所有父级的文件名。 因此,仅当使用 --diff-merges=[dense-]combined 时才有效, 并且可能仅在检测到文件名更改时(即请求了重命名或复制检测时)才有用。 endif::git-log[]

-U<n>:: --unified=<n>:: 生成具有 <n> 行上下文的差异。上下文 行数默认为 diff.context,如果未设置配置变量 则为 3。

ifndef::git-format-patch[] 隐含 --patch。 endif::git-format-patch[]

--output=<file>:: 输出到指定文件而不是标准输出。

--output-indicator-new=<char>:: --output-indicator-old=<char>:: --output-indicator-context=<char>:: 指定在生成的补丁中用于指示新行、旧行或上下文行的字符。 通常它们分别是 +- 和 ' '。

ifndef::git-format-patch[] --raw:: ifndef::git-log[] 以原始格式生成差异。 ifdef::git-diff-core[] 这是默认行为。 endif::git-diff-core[] endif::git-log[] ifdef::git-log[] 对于每个提交,使用原始差异格式显示更改摘要。 参见 git-diff(1) 中的"原始输出格式"部分。 这与以原始格式显示日志本身不同, 您可以通过 --format=raw 来实现。 endif::git-log[] endif::git-format-patch[]

ifndef::git-format-patch[] --patch-with-raw:: -p --raw 的同义词。 endif::git-format-patch[]

ifdef::git-log[] -t:: 在差异输出中显示树对象。 endif::git-log[]

--indent-heuristic:: 启用启发式方法,调整差异块边界以使补丁更易读。这是默认行为。

--no-indent-heuristic:: 禁用缩进启发式。

--minimal:: 花费额外时间以确保产生尽可能小的差异。

--patience:: 使用"耐心差异"算法生成差异。

--histogram:: 使用"直方图差异"算法生成差异。

--anchored=<text>:: 使用"锚定差异"算法生成差异。 + 此选项可以指定多次。 + 如果一行同时存在于源和目标中,仅出现一次, 并且以 <text> 开头,则此算法尝试防止该行在输出中显示为删除或添加。 它内部使用"耐心差异"算法。

--diff-algorithm=(patience|minimal|histogram|myers):: 选择差异算法。变体如下:

+

diff.wsErrorHighlight:: 在差异的 contextoldnew 行中高亮显示空白错误。 多个值用逗号分隔,none 重置之前的值, default 将列表重置为 newallold,new,context 的简写。 空白错误使用 color.diff.whitespace 着色。 命令行选项 --ws-error-highlight=<kind> 会覆盖此设置。

diff.colorMoved:: 如果设置为有效的 <mode>true 值, 差异中移动的行将以不同颜色显示。 ifdef::git-diff[] 有关有效模式的详细信息,请参阅 --color-moved。 endif::git-diff[] ifndef::git-diff[] 有关有效模式的详细信息,请参阅 git-diff(1) 中的 --color-moved。 endif::git-diff[] 如果简单设置为 true,将使用默认颜色模式。 设置为 false 时,移动的行不会着色。

diff.colorMovedWS:: 当使用 diff.colorMoved 设置对移动的行着色时, 此选项控制空白处理的模式。 有关有效模式的详细信息,请参阅 git-diff(1) 中的 --color-moved-ws

+

示例:以下将统计更改的文件,同时忽略 更改文件总数少于 10% 的目录, 并在父目录中累积子目录计数: files,10,cumulative

diff.statNameWidth:: 限制 --stat 输出中文件名部分的宽度。如果设置, 适用于除 format-patch 外所有生成 --stat 输出的命令。

diff.statGraphWidth:: 限制 --stat 输出中图形部分的宽度。如果设置, 适用于除 format-patch 外所有生成 --stat 输出的命令。

diff.context:: 生成具有 <n> 行上下文的差异而不是默认的 3 行。 此值会被 -U 选项覆盖。

diff.interHunkContext:: 显示差异块之间的上下文,最多指定行数, 从而融合彼此接近的块。 此值作为 --inter-hunk-context 命令行选项的默认值。

diff.external:: 如果设置了此配置变量,差异生成将不使用内部差异机制, 而是使用给定的命令。可以使用 GIT_EXTERNAL_DIFF 环境变量覆盖。 该命令的调用参数描述见 git(1) 中的"git 差异"。 注意:如果您只想对部分文件使用外部差异程序, 您可能需要使用 gitattributes(5)

diff.trustExitCode:: 如果此布尔值设置为 true,则 diff.external 命令 在认为输入文件相等时应返回退出码 0, 在认为它们不同时应返回 1,类似于 diff(1)。 如果设置为 false(默认值),则命令应返回退出码 0, 无论是否相等。任何其他退出码会导致 Git 报告致命错误。

diff.ignoreSubmodules:: 设置 --ignore-submodules 的默认值。请注意,这仅影响 git diff 瓷器命令,不影响低级别的 diff 命令(如 git diff-files)。 git checkoutgit switch 在报告未提交的更改时也会遵循此设置。 将其设置为 all 会禁用 git commitgit statusstatus.submoduleSummary 设置时通常显示的子模块摘要, 除非使用 --ignore-submodules 命令行选项覆盖。 git submodule 命令不受此设置影响。 默认设置为 untracked,因此任何未跟踪的子模块都会被忽略。

diff.mnemonicPrefix:: 如果设置,git diff 会使用根据比较内容不同的前缀对, 而不是标准的 a/b/。当此配置生效时, 反向差异输出也会交换前缀的顺序: git diff;; 比较 (i)ndex(索引)和 (w)ork tree(工作树); git diff HEAD;; 比较 (c)ommit(提交)和 (w)ork tree(工作树); git diff --cached;; 比较 (c)ommit(提交)和 (i)ndex(索引); git diff HEAD:<file1> <file2>;; 比较 (o)bject(对象)和 (w)ork tree(工作树)实体; git diff --no-index <a> <b>;; 比较两个非 git 事物 <a><b>

diff.noPrefix:: 如果设置,git diff 不显示任何源或目标前缀。

diff.srcPrefix:: 如果设置,git diff 使用此源前缀。默认为 a/

diff.dstPrefix:: 如果设置,git diff 使用此目标前缀。默认为 b/

diff.relative:: 如果设置为 truegit diff 不显示目录之外的更改, 并显示相对于当前目录的路径名。

diff.orderFile:: 指定如何在差异中排序文件的文件。 ifdef::git-diff[] 详细信息请参阅 -O 选项。 endif::git-diff[] ifndef::git-diff[] 详细信息请参阅 git-diff(1)-O 选项。 endif::git-diff[] 如果 diff.orderFile 是相对路径名, 则将其视为相对于工作树的顶部。

diff.renameLimit:: 在复制/重命名检测的穷举部分中考虑的文件数量; 等同于 git diff 选项 -l。如果未设置, 默认值目前为 1000。如果禁用了重命名检测,此设置无效。

diff.renames:: Git 是否以及如何检测重命名。如果设置为 false, 禁用重命名检测。如果设置为 true,启用基本重命名检测。 如果设置为 copiescopy,Git 也会检测复制。 默认为 true。请注意,这仅影响 git diff 瓷器命令 (如 git-diff(1)git-log(1)), 不影响低级别命令(如 git-diff-files(1))。

diff.suppressBlankEmpty:: 一个布尔值,用于抑制在每个空输出行前打印空格的标准行为。 默认为 false

diff.submodule:: 指定子模块差异的显示格式。short 格式仅显示范围开始和结束的提交名称。 log 格式列出范围内的提交,类似于 git-submodule(1) summarydiff 格式显示子模块更改内容的内联差异。默认为 short

diff.wordRegex:: 一个 POSIX 扩展正则表达式,用于在执行逐词差异计算时确定什么是"词"。 匹配正则表达式的字符序列是"词",所有其他字符是可忽略的空白。

diff.<driver>.command:: 自定义差异驱动程序命令。详细信息请参阅 gitattributes(5)

diff.<driver>.trustExitCode:: 如果此布尔值设置为 true,则 diff.<driver>.command 命令 在认为输入文件相等时应返回退出码 0, 在认为它们不同时应返回 1,类似于 diff(1)。 如果设置为 false(默认值),则命令应返回退出码 0, 无论是否相等。任何其他退出码会导致 Git 报告致命错误。

diff.<driver>.xfuncname:: 差异驱动程序用于识别块头的正则表达式。 也可以使用内置模式。 详细信息请参阅 gitattributes(5)

diff.<driver>.binary:: 将此选项设置为 true 可使差异驱动程序将文件视为二进制文件。 详细信息请参阅 gitattributes(5)

diff.<driver>.textconv:: 差异驱动程序应调用的命令,用于生成文件的文本转换版本。 转换的结果用于生成人类可读的差异。 详细信息请参阅 gitattributes(5)

diff.<driver>.wordRegex:: 差异驱动程序用于在一行中分词的正则表达式。 详细信息请参阅 gitattributes(5)

diff.<driver>.cachetextconv:: 将此选项设置为 true 可使差异驱动程序缓存文本转换输出。 详细信息请参阅 gitattributes(5)

diff.indentHeuristic:: 将此选项设置为 false 可禁用默认的启发式方法, 该方法会调整差异块边界以使补丁更易读。

diff.algorithm:: 选择差异算法。变体如下:

+

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

--color-moved-ws=<mode>,...:: 配置在执行 --color-moved 的移动检测时如何忽略空白。 ifdef::git-diff[] 可以通过 diff.colorMovedWS 配置设置来设置。 endif::git-diff[] 这些模式可以作为逗号分隔的列表给出:

+

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

--word-diff[=<mode>]:: 默认情况下,词由空白分隔;参见下面的 --word-diff-regex<mode> 默认为 plain,必须是以下之一:

+

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

--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>。 endif::git-format-patch[]

--no-renames:: 关闭重命名检测,即使配置文件给出了默认值。

--rename-empty:: --no-rename-empty:: 是否使用空的 blob 作为重命名源。

ifndef::git-format-patch[] --check:: 如果更改引入冲突标记或空白错误则发出警告。 什么被视为空白错误由 core.whitespace 配置控制。 默认情况下,尾随空白(包括仅由空白组成的行) 和行初始缩进中紧跟制表符的空格字符被视为空白错误。 如果发现问题则以非零状态退出。与 --exit-code 不兼容。

--ws-error-highlight=<kind>:: 在差异的 contextoldnew 行中高亮显示空白错误。 多个值用逗号分隔,none 重置之前的值, default 将列表重置为 newallold,new,context 的简写。 当未给出此选项且配置变量 diff.wsErrorHighlight 未设置时, 仅高亮显示 new 行中的空白错误。 空白错误使用 color.diff.whitespace 着色。

endif::git-format-patch[]

--full-index:: 在生成补丁格式输出时,在"index"行显示完整的变更前后 blob 对象名称,而不是前几个字符。

--binary:: 除了 --full-index 外,还输出可以用 git-apply 应用的二进制差异。 ifndef::git-format-patch[] 隐含 --patch。 endif::git-format-patch[]

--abbrev[=<n>]:: 在 diff-raw 格式输出和 diff-tree 头行中, 显示至少 <n> 个十六进制数字长的最短前缀来唯一标识对象, 而不是显示完整的 40 字节十六进制对象名称。 在 diff-patch 输出格式中,--full-index 优先级更高, 即如果指定了 --full-index,无论是否使用 --abbrev 都会显示完整的 blob 名称。 可以使用 --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>]:: ifndef::git-log[] 检测重命名。 endif::git-log[] ifdef::git-log[] 如果生成差异,为每个提交检测并报告重命名。 有关在遍历历史时跟踪重命名,请参阅 --follow。 endif::git-log[] 如果指定了 <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<num>:: -M-C 选项涉及一些初步步骤, 可以廉价地检测重命名/复制的子集, 然后是穷举回退部分,将所有剩余的未配对目标与所有相关源进行比较。 (对于重命名,只有剩余的未配对源是相关的; 对于复制,所有原始源都是相关的。) 对于 N 个源和目标,此穷举检查是 O(N^2)。 如果涉及的源/目标文件数量超过指定数量, 此选项会阻止重命名/复制检测的穷举部分运行。 默认为 diff.renameLimit。请注意,值 0 被视为无限制。

ifndef::git-format-patch[] --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> 在文件中出现次数(即添加/删除)的差异。 供脚本编写者使用。 + 当您正在查找确切的代码块(如结构体), 并希望了解该块自首次出现以来的历史时很有用: 迭代地使用此功能将变更前的有趣块反馈给 -S, 并继续直到获得该块的最初版本。 + 也会搜索二进制文件。

-G<regex>:: 查找补丁文本包含与 <regex> 匹配的添加/删除行的差异。 + 为了说明 -S<regex> --pickaxe-regex-G<regex> 之间的区别, 考虑一个在同一文件中具有以下差异的提交:

+

虽然 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 正则表达式。

endif::git-format-patch[]

-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 命令创建的, 在其他情况下可能不太有用。

ifndef::git-format-patch[] -R:: 交换两个输入;即显示从索引或磁盘文件到树内容的差异。 endif::git-format-patch[]

--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) 中的"自定义块头")。

ifndef::git-format-patch[] ifndef::git-log[] --exit-code:: 使程序以类似于 diff(1) 的退出码退出。 即,如果有差异则退出码为 1,无差异则为 0。

--quiet:: 禁用程序的所有输出。隐含 --exit-code。 禁用退出码不受信任的外部差异辅助程序的执行, 即其相应的配置选项 diff.trustExitCode 或 ++diff.++<driver>++.trustExitCode++ 或环境变量 GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE 为 false。 endif::git-log[] endif::git-format-patch[]

--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:: ifdef::git-format-patch[] 使用默认的源和目标前缀("a/" 和 "b/")。 这会覆盖配置变量,如 format.noprefixdiff.srcPrefixdiff.dstPrefixdiff.mnemonicPrefix (参见 git-config(1))。 endif::git-format-patch[] ifndef::git-format-patch[] 使用默认的源和目标前缀("a/" 和 "b/")。 这会覆盖配置变量,如 diff.noprefixdiff.srcPrefixdiff.dstPrefixdiff.mnemonicPrefix (参见 git-config(1))。 endif::git-format-patch[]

--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。 这允许您在请求顶级条目的子集时仍然限制深度。 + 请注意,此选项仅支持树对象之间的差异,不支持与索引或工作树的差异。

有关这些通用选项的更详细说明,请另请参阅 gitdiffcore(7)

-1:: --base:: -2:: --ours:: -3:: --theirs:: 将工作树与

+

索引仅在未合并的条目中包含这些阶段,即在解决冲突时。 详细信息请参阅 git-read-tree(1) 的"三路合并"部分。

-0:: 省略未合并条目的差异输出,仅显示"Unmerged"。 仅在将工作树与索引进行比较时可以使用。

<path>...:: <path> 参数给出时,用于将差异限制为指定的路径 (可以给出目录名并获取其下所有文件的差异)。

原始输出格式

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-files 在未合并文件的情况下例外, 它同时打印"unmerged"和"in-place edit"行。

输出行的格式如下:

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" 的模式;如果是创建,或 "src" 来自索引且未合并,则为 000000。
  3. 一个空格。
  4. "dst" 的模式;如果是删除,或 "dst" 来自索引且未合并,则为 000000。
  5. 一个空格。
  6. "src" 的 sha1;如果是创建,或 "src" 来自索引且未合并,则为 0{40}。
  7. 一个空格。
  8. "dst" 的 sha1;如果是删除,"dst" 来自索引且未合并,或 "dst" 来自工作树且与索引不同步,则为 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 字节终止。

合并的 diff 格式

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

  1. 每个父级有一个冒号
  2. 有更多"src"模式和"src" sha1
  3. 状态是每个父级的状态字符连接
  4. 没有可选的"分数"数字
  5. 文件的制表符分隔路径名

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

不使用 --combined-all-paths-c--cc 示例:

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

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

[[generate_patch_text_with_p]]

使用 -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 选项产生的内容与传统差异格式略有不同:

  1. 它前面有一个"git diff"头,如下所示:

    diff --git a/file1 b/file2

a/b/ 文件名是相同的,除非涉及重命名/复制。 特别是,即使对于创建或删除,也不会使用 /dev/null 代替 a/b/ 文件名。 + 当涉及重命名/复制时,file1file2 分别显示重命名/复制的源文件名和重命名/复制产生的文件名。

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

[synopsis] 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>; 否则,单独的行指示旧模式和新模式。

  1. 包含"异常"字符的路径名按照配置变量 core.quotePath 的说明进行引用 (参见 git-config(1))。

  2. 输出中所有 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

  3. 块头提到块适用的函数名称。 详细信息请参阅 gitattributes(5) 中的"自定义块头", 了解如何针对特定语言进行定制。

组合 diff 格式

任何生成差异的命令都可以使用 -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
  1. 后面跟着一个或多个扩展头行 (此示例显示有两个父级的合并):

[synopsis] index <hash>,<hash>..<hash> mode <mode>,<mode>..<mode> new file mode <mode> deleted file mode <mode>,<mode> + mode <mode>,<mode>..<mode> 行仅在至少一个 <mode> 与其他不同时出现。 包含检测到的内容移动信息(重命名和复制检测)的扩展头 设计用于两个 <tree-ish> 的差异,不被组合差异格式使用。

  1. 后面跟着两行 from-file/to-file 头:

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

类似于传统"统一"差异格式的两行头, /dev/null 用于表示创建或删除的文件。 + 但是,如果提供了 --combined-all-paths 选项, 则不是两行 from-file/to-file,而是 N+1 行 from-file/to-file 头, 其中 N 是合并提交中的父级数量:

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

如果重命名或复制检测处于活动状态,此扩展格式可用于 查看不同父级中的原始文件名。

  1. 块头格式被修改以防止人们意外将其馈送给 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 的行与其有何不同。

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

在上面的示例输出中,函数签名从两个文件中都更改了 (因此从 file1 和 file2 中都有两个 - 删除, 加上 ++ 表示添加的一行不出现在 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 =&gt; 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 diff AUTO_MERGE <4>

<1> 工作树中尚未暂存的更改。 <2> 索引与上次提交之间的更改;如果不使用 -a 选项运行 git commit 将会提交的内容。 <3> 工作树中自上次提交以来的更改;如果运行 git commit -a 将会提交的内容。 <4> 您迄今为止为解决文本冲突而在工作树中所做的更改。

比较任意提交::

$ git diff HEAD^ HEAD <3>

<1> 不使用当前分支的顶端,而是与"test"分支的顶端进行比较。 <2> 不与"test"分支的顶端进行比较,而是与当前分支的顶端进行比较, 但将比较限制为文件"test"。 <3> 比较上次提交之前的版本和上次提交。

比较分支::

$ git diff topic...master <3>

<1> topic 和 master 分支顶端之间的更改。 <2> 与上面相同。 <3> topic 分支从 master 分支创建以来在 master 分支上发生的更改。

限制差异输出::

$ git diff arch/i386 include/asm-i386 <3>

<1> 仅显示修改、重命名和复制,不显示添加或删除。 <2> 仅显示名称和更改性质,不显示实际差异输出。 <3> 将差异输出限制为指定的子树。

修改差异输出::

$ git diff -R <2>

<1> 花费额外的周期来查找重命名、复制和完全重写(非常昂贵)。 <2> 反向输出差异。

配置

本节中此行以下的所有内容都是从 git-config(1) 文档中选择性包含的。内容与其中的内容相同:

:git-diff: 1 diff.autoRefreshIndex:: 使用 git diff 与工作树文件进行比较时, 不将仅 stat 的更改视为已更改。 而是静默运行 git update-index --refresh 来更新 工作树中内容与索引中内容匹配的路径的缓存 stat 信息。 此选项默认为 true。请注意,这仅影响 git diff 瓷器命令, 不影响低级别的 diff 命令(如 git diff-files)。

diff.dirstat:: ifdef::git-diff[] 逗号分隔的 --dirstat 参数列表,指定 git diff 及其相关命令的 --dirstat 选项的默认行为。 endif::git-diff[] ifndef::git-diff[] 逗号分隔的 --dirstat 参数列表,指定 git-diff(1) 及其相关命令的 --dirstat 选项的默认行为。 endif::git-diff[] 可以在命令行上覆盖默认值(使用 --dirstat=<param>,...)。 回退默认值(未被 diff.dirstat 更改时)为 changes,noncumulative,3。 以下参数可用:

另请参阅

diff(1), git-difftool(1), git-log(1), gitdiffcore(7), git-format-patch(1), git-apply(1), git-show(1)

Git

git(1) 套件的一部分

基于 CC BY-NC-SA 3.0 许可发布