非常教程

Git参考手册

基本快照 | Basic Snapshotting

git diff

命名

git-diff - 显示提交,提交和工作树等之间的变化

概要

git diff [options] [<commit>] [--] [<path>…​]
git diff [options] --cached [<commit>] [--] [<path>…​]
git diff [options] <commit> <commit> [--] [<path>…​]
git diff [options] <blob> <blob>
git diff [options] [--no-index] [--] <path> <path>

描述

显示工作树与索引或树之间的更改,索引与树之间的更改,两棵树之间的更改,两个 Blob 对象之间的更改或磁盘上两个文件之间的更改。

git diff --options <path>…​

这种形式是查看你相对于索引所做的更改(下一次提交的暂存区域)。换句话说,不同之处在于你could告诉 Git 进一步添加到索引中,但你仍然没有。您可以使用 git-add [1]来完成这些更改。

git diff --no-index --options <path>…​

这种形式是比较文件系统上给定的两个路径。--no-index在由 Git 控制的工作树中运行命令时,可以省略该选项,并且至少有一个路径位于工作树之外,或者在由 Git 控制的工作树之外运行该命令。

git diff --options --cached <commit> <path>…​

这种形式是查看您为下一次提交相对于指定的 <commit> 进行的更改。通常情况下,您需要与最新的提交进行比较,所以如果您不提供 <commit> ,则默认为 HEAD 。如果 HEAD 不存在(例如未出生的分支)并且未提供 <commit> ,则会显示所有分阶段更改。--staged 是 --cached 的同义词。

git diff --options <commit> --

这种形式是查看您的工作树中相对于名为 <commit> 的变化。您可以使用 HEAD 将其与最新的提交进行比较,或使用分支名称与不同分支的提示进行比较。

git diff --options <commit> <commit> --

这是查看两个任意 <commit> 之间的变化。

git diff --options <commit>..<commit> --

这是以前的形式的代名词。如果忽略一侧的 <commit> ,它将具有与使用 HEAD 相同的效果。

git diff --options <commit>...<commit> --

这种形式是查看包含第二个 <commit> 的分支上的更改,从两个 <commit> 的共同祖先开始。“git diff A ... B” 相当于 “git diff $(git-merge-base AB)B”。您可以省略 <commit> 中的任何一个,它与使用 HEAD 具有相同的效果。

以防万一,如果你正在做一些奇特的事情,应该注意的是,除了最后两个使用“..”符号的形式,上述描述中的所有 <commit> 都可以是任何 <tree> 。

有关拼写 <commit> 的更完整列表,请参阅 gitrevisions [7] 中的“指定修订”部分。然而,“差异”是关于比较两个endpoints,而不是范围,范围符号( “<commit> .. <commit>” 和 “<commit> ... <commit>” )并不意味着如 gitrevisions 中的“指定范围”部分[7]。

git diff options <blob> <blob>

这种形式是查看两个 blob 对象的原始内容之间的差异。

选项

-p -u --patch

生成补丁(请参阅生成补丁一节)。这是默认设置。

-s --no-patch

抑制差异输出。对于像git show这样的命令很有用,默认显示补丁,或者取消效果--patch

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

使用 <n> 行上下文生成差异,而不是通常的三行。意味着-p

--raw

以原始格式生成差异。

--patch-with-raw

-p --raw的同义词。

--indent-heuristic --no-indent-heuristic

这些是为了帮助调试和调整实验启发式(默认情况下是关闭的),这些启发式技术改变了差异边界以使修补程序更易于阅读。

--minimal

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

--patience

使用“耐心差异”算法生成差异。

--histogram

使用“直方图差异”算法生成差异。

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

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

default, myers

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

minimal

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

patience

生成补丁时使用“耐心差异”算法。

histogram

该算法将耐心算法扩展为“支持低出现率的通用元素”。

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

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

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

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

--numstat

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

--shortstat

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

--dirstat=<param1,param2,…​>

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

changes

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

lines

通过执行常规基于行的差异分析来计算 dirstat 数字,并且将移除/添加的行数相加。(对于二进制文件,取而代之的是计算64字节的块,因为二进制文件没有自然的行概念)。这是一种--dirstatchanges行为更为昂贵的行为,但它可以像其他更改一样对文件中的重新排列的行进行计数。结果输出与您从其他--*stat选项中获得的结果一致。

files

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

cumulative

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

<limit>

整数参数指定截断百分比(默认为3%)。输出中不显示贡献小于此百分比的目录。

示例:以下内容将计数已更改的文件,同时忽略占已更改文件总数少于10%的目录,并累积父目录中的子目录计数:--dirstat=files,10,cumulative

--summary

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

--patch-with-stat

-p --stat的同义词。

-z

--raw--numstat--name-only--name-status已给出,时间路径名信息变换完全,并使用完全无效的输出字段终止符。

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

--name-only

仅显示已更改文件的名称。

--name-status

仅显示已更改文件的名称和状态。有关--diff-filter状态字母的含义,请参阅选项说明。

--submodule=<format>

指定如何显示子模块中的差异。指定使用--submodule=shortshort格式时。这种格式只显示范围开始和结束处的提交名称。当--submodule或者--submodule=log被指定时,使用log格式。这种格式列出了像 git-submodule [1] summary那样的提交。当--submodule=diff指定时,使用diff格式。这种格式显示了提交范围内子模块内容变化的内联比较。如果配置选项未设置,则默认为diff.submoduleshort格式。

--color=<when>

显示有色差异。--color(即没有=<when>)是一样的--color=always<when>可以是一个alwaysneverauto。它可以通过color.uicolor.diff配置设置进行更改。

--no-color

关闭有色差异。这可以用来覆盖配置设置。它和--color=never一样。

--word-diff=<mode>

显示一个单词 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=.将每个字符看作单词,并相应地逐个字符地显示差异。

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

--color-words=<regex>

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

--no-renames

关闭重命名检测,即使配置文件提供了默认设置。

--check

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

--ws-error-highlight=<kind>

突出显示空白的错误contextold或者new把差异线。多个值以逗号分隔,none重置以前的值,default将列表重置为newall简写为old,new,context。如果未给出此选项,并且diff.wsErrorHighlight未设置配置变量,则只会new突出显示行中的空白错误。空白错误是彩色的color.diff.whitespace

--full-index

在生成补丁格式输出时,在“索引”行上显示完整的映像前和映像后 blob 对象名称,而不是第一批字符。

--binary

除了--full-index输出可以应用的二进制差异git-apply

--abbrev=<n>

不是在 diff-raw 格式输出和 diff-tree 标题行中显示完整的40字节十六进制对象名称,只显示部分前缀。这与--full-index上面的选项无关,后者控制 diff-patch 输出格式。非默认的位数可以用指定--abbrev=<n>

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

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

它影响到一种改变的方式,这种改变相当于整个文件的重写,而不是像一系列删除和插入混合在一起,只有几行文字与上下文相匹配,而是作为旧的一切的一次删除,单次插入所有新事物,并且数字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<num>

-M-C选项需要为 O(n ^ 2)的处理时间,其中 n 是/复制目标潜在的重命名的数目。如果重命名/复制目标的数量超过指定的数量,则此选项可防止重命名/复制检测运行。

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

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

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

-S<string>

查找改变文件中指定字符串出现次数(即添加/删除)的差异。旨在供剧本使用。

当你寻找一个精确的代码块(比如一个结构体)并且想要知道该块自第一次出现以来的历史记录时,它非常有用:迭代地使用该特征将原始图像中的有趣块返回到-S,并继续前进,直到获得该块的第一个版本。

-G<regex>

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

为了说明之间的区别-S<regex> --pickaxe-regex,并-G<regex>考虑在同一个文件中的以下 DIFF 提交:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

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

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

--pickaxe-all

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

--pickaxe-regex

将给定的 <string> -S视为扩展的 POSIX 正则表达式进行匹配。

-O<orderfile>

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

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

按以下方式解析 <orderfile> :

  • 空白行被忽略,所以它们可以用作分隔符以提高可读性。
  • 以散列(“ #”)开头的行会被忽略,因此它们可以用于注释。\如果以散列开头,则在模式的开头添加反斜杠(“ ”)。
  • 每隔一行包含一个模式。

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

-R

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

--relative=<path>

当从项目的子目录运行时,可以通过该选项告知排除目录外的更改并显示与其相关的路径名。如果不在子目录中(例如,在裸存储库中),可以通过给出 <path> 作为参数来命名将哪个子目录作为输出的相对位置。

-a --text

将所有文件视为文本。

--ignore-space-at-eol

忽略 EOL 中的空白变化。

-b --ignore-space-change

忽略空白量的变化。这会忽略行结束处的空白,并认为一个或多个空白字符的所有其他序列是等价的。

-w --ignore-all-space

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

--ignore-blank-lines

忽略其行全部空白的更改。

--inter-hunk-context=<lines>

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

-W --function-context

显示整个周围的变化功能。

--exit-code

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

--quiet

禁用程序的所有输出,意味着--exit-code

--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 plumbing 命令。

--ignore-submodules=<when>

忽略差异代中子模块的更改。<when> 可以是 “none” ,“untracked” ,“dirty” 或 “all” ,这是默认设置。如果子模块包含未跟踪或已修改的文件,或者 HEAD 与超级项目中记录的提交不同,并且可用于覆盖ignore git-config [1] 或 gitmodules [5] 中的任何选项设置,则使用 “none” ]。当使用“未跟踪”时,如果子模块仅包含未跟踪内容(但仍然针对修改内容进行扫描),则子模块不会被视为脏。使用 “dirty” 会忽略对子模块工作树的所有更改,只会显示超级项目中存储的提交更改(这是1.7.0之前的行为)。使用“全部”隐藏所有子模块的变化

--src-prefix=<prefix>

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

--dst-prefix=<prefix>

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

--no-prefix

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

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

-1 --base -2 --ours -3 --theirs

比较工作树与“基本”版本(阶段#1),“我们的分支”(阶段#2)或“他们的分支”(阶段#3)。该索引仅包含未组合的条目的这些阶段,即在解决冲突时。有关详细信息,请参阅 git-read-tree [1] 部分 “3-Way Merge” 。

-0

忽略差异输出未合并的条目并只显示“未合并”。仅在将工作树与索引进行比较时才能使用。

<path>…​

给出的 <paths> 参数用于将 diff 限制为指定的路径(您可以给出目录名称并为其下的所有文件获取 diff )。

原始输出格式

“git-diff-index” ,“git-diff-tree” ,“git-diff-files” 和 “git 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. a colon.
  2. mode for "src"; 000000 if creation or unmerged.
  3. a space.
  4. mode for "dst"; 000000 if deletion or unmerged.
  5. a space.
  6. sha1 for "src"; 0{40} if creation or unmerged.
  7. a space.
  8. sha1 for "dst"; 0{40} if creation, unmerged or "look at work tree".
  9. a space.
  10. status, followed by optional "score" number.
  11. a tab or a NUL when -z option is used.
  12. path for "src"
  13. a tab or a NUL when -z option is used; only exists for C or R.
  14. path for "dst"; only exists for C or R.
  15. an LF or a NUL when -z option is used, to terminate the record.

可能的状态字母是:

  • A:添加一个文件
  • C:将文件复制到新文件中
  • D:删除文件
  • M:修改文件的内容或模式
  • R:重命名文件
  • T:改变文件的类型
  • U:文件未合并(必须先完成合并,然后才能提交)
  • X:“未知”更改类型(最可能是一个错误,请报告)

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

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

例:

:100644 100644 5be4a4...... 000000...... M file.c

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

比较格式的合并

“混帐的Diff-树” ,“混帐的Diff-文件” 和 “混帐DIFF --raw” 可以采取-c--cc选项,也产生差异输出合并提交。输出与上述格式的不同之处在于:

  1. 每个父母都有一个冒号
  2. 还有更多的 “src” 模式和 “src” sha1
  3. 状态是每个父级的连接状态字符
  4. 没有可选的 “分数” 号码
  5. 单一路径,仅适用于 “dst”

例:

::100644 100644 100644 fabadb8... cc95eb0... 4866510... MM        describe.c

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

用 -p 生成补丁

当使用选项运行 “git-diff-index” ,“git-diff-tree” 或 “git-diff-files” 时,不带-p选项运行 “git diff” --raw,使用 “-p” 运行 “git log” 选项,它们不会产生上述输出; 相反,他们生成一个补丁文件。您可以通过GIT_EXTERNAL_DIFFGIT_DIFF_OPTS环境变量自定义这些修补程序的创建。

-p 选项产生的东西与传统的 diff 格式略有不同:

  1. 它前面有一个 “git diff” 头文件,它看起来像这样:diff --git a / file1 b / file2

a/b/文件名是,除非重命名/副本所涉及的相同。尤其是,即使是创建或删除,/dev/null也可not用于替换文件名a/b/文件名。

当重命名/复制参与,file1file2示出了重命名/复制的源文件的名称和重命名/复制分别产生,该文件的名称。

  1. 它后跟一个或多个扩展标题行:旧模式 <mode> 新模式 <mode> 已删除文件模式 <mode> 新文件模式 <mode> 从 <path> 复制到 <path> 从 <path> 重命名为 <path> 相似索引 <number> 不相似索引 <number> 索引 <hash> .. <hash> <mode>

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

扩展标题中的路径名称不包含a/b/前缀。

相似性指数是未改变的行的百分比,不相似性指数是改变的行的百分比。它是一个向下舍入的整数,后面跟着一个百分号。100%的相似性指数值因此保留给两个相同的文件,而100%相异性意味着来自旧文件的任何行都不会将其转换为新的文件。

索引行包含更改前后的 SHA-1 校验和。如果文件模式没有改变,则包含 <mode> ; 否则,单独的行表示旧模式和新模式。

  1. 带有“不常用”字符的路径名将按照配置变量的说明引用core.quotePath(请参阅 git-config [1] )。
  2. file1输出中的所有文件在提交之前引用文件,所有file2文件在提交之后引用文件。将每个更改顺序应用于每个文件是不正确的。例如,这个补丁会将 a 和 b :diff --git a / ab / b 重命名为重命名为 b diff --git a / bb / a 将重命名从 b 重命名为 a

结合 diff 格式

任何 diff-generating 命令都可以使用-c--cc选项combined diff在显示合并时生成一个。这是显示与 git-diff [1] 或 git-show [1]合并时的默认格式。还要注意,您可以-m选择这些命令中的任何一个来强制生成合并的单个父代的差异。

一个combined 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 - 组合文件

或者像这样(当使用--cc选项时):

diff --cc file

  1. 它后面跟着一个或多个扩展标题行(此示例显示与两个父级合并):index <hash>,<hash> .. <hash> mode <mode>,<mode> .. <mode>新文件模式 <mode> 删除文件模式 <mode> ,<mode>

mode <mode>,<mode>..<mode>行仅在至少有一个 <mode> 与其他行不同时出现。具有关于检测到的内容移动(重命名和复制检测)的信息的扩展标题被设计为与两个 <tree-ish> 的差异一起工作,并且不被组合的差异格式使用。

  1. 紧接着是 two-line from-file/to-file header --- a / file +++ b / file

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

  1. 块头格式被修改以防止人们意外地将其提供给patch -p1。组合的差异格式是为了审查合并提交更改而创建的,并不适用于应用。此更改与扩展index标头中的更改类似:@@@ <from-file-range> <from-file-range> <to-file-range> @@@

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

与传统的unified差异格式不同,该格式显示两个文件 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 aka “我们的版本”,file2 是阶段3 aka “他们的版本”)。

其他差异格式

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

NUL重命名之前的 preimage 路径之前的额外内容是允许读取输出的脚本判断当前正在读取的记录是单路径记录还是重命名/复制记录,而不提前读取。阅读添加和删除的行后,读取NUL会产生路径名,但如果是这样NUL,该记录将显示两个路径。

例子

各种方法来检查你的工作树

$ git diff            (1)
$ git diff --cached   (2)
$ git diff HEAD       (3)
  1. 下一次提交的工作树中的更改尚未完成。
  2. 索引和上次提交之间的变化; 如果你运行 “git commit” 而没有 “-a” 选项,你会提交什么。
  3. 自上次提交以来工作树中的更改; 你会运行 “git commit -a”

与任意提交进行比较

$ git diff test            (1)
$ git diff HEAD -- ./test  (2)
$ git diff HEAD^ HEAD      (3)
  1. 而不是使用当前分支的尖端,与“测试”分支的尖端进行比较。
  2. 与“测试”分支的尖端进行比较,而不是与当前分支的尖端进行比较,但将比较限制为“测试”文件。
  3. 比较上次提交和上次提交之前的版本。

比较分支机构

$ git diff topic master    (1)
$ git diff topic..master   (2)
$ git diff topic...master  (3)
  1. 主题提示与主分支之间的变化。
  2. 同上。
  3. 自主题分支启动时发生在主分支上的更改。

限制差异输出

$ git diff --diff-filter=MRC            (1)
$ git diff --name-status                (2)
$ git diff arch/i386 include/asm-i386   (3)
  1. 只显示修改,重命名和复制,但不能添加或删除。
  2. 只显示名称和变化的性质,但不显示实际的差异输出。
  3. 限制差异输出到指定的子树。

扼杀差异输出

$ git diff --find-copies-harder -B -C  (1)
$ git diff -R                          (2)
  1. 花费额外的周期来查找重命名,复制和完整重写(非常昂贵)。
  2. 输出 diff 反向。