非常教程

Git参考手册

Plumbing Commands

git diff-index

名称

git-diff-index - 比较树与工作树或索引

概要

git diff-index [-m] [--cached] [<common diff options>] <tree-ish> [<path>…​]

描述

将树对象中发现的斑点的内容和模式与工作树中相应的跟踪文件或索引中的相应路径进行比较。当<path>参数存在时,只比较匹配这些模式的路径。否则,将比较所有跟踪的文件。

选项

-p -u --patch

生成补丁(请参阅生成补丁一节)。

-s - 无补丁

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

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

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

--raw

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

--patch-with-raw

-p --raw的同义词。

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

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

--minimal

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

--patience

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

--histogram

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

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

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

default, myers

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

minimal

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

patience

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

histogram

该算法将耐心算法扩展为“support low-occurrence common elements(支持低出现率的通用元素)”。

例如,如果您将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已给出,不Munge时间路径名,并使用完全无效的输出字段终止符。

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

--name-only

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

--name-status

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

--submodule=<format>

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

--color=<when>

显示有色差异。--color(即没有=<when>)是一样的--color=always<when>可以是一个alwaysneverauto

--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或git-config。显式给予它将覆盖任何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

在生成补丁格式输出时,在“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; 这仅适用于那些想专注于更改后查看文本的人。另外,输出显然缺乏足够的信息来反向应用这样的补丁,甚至是手动的,因此也就是选项的名称。

在与-Bdelete/create对的删除部分一起使用时,还要省略原像。

-l<num>

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

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

选择仅Added (A), Copied (C),Deleted (D),Modified (M),Renamed (R),其类型(即常规文件,符号链接,子模块,...)changed (T), Unmerged (U), 是 Unknown (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中的条目。

--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设置外部差异驱动程序,你需要在git-log和朋友中使用这个选项。

--no-ext-diff

禁止外部差异驱动程序。

--textconv --no-textconv

在比较二进制文件时,允许(或不允许)运行外部文本转换过滤器。有关详细信息,请参阅gitattributes。由于textconv过滤器通常是单向转换,因此生成的差异适合人类消费,但无法应用。出于这个原因,默认情况下,textconv过滤器仅针对git-diff和git-log启用,但不适用于git-format-patch或diff plumbing命令。

--ignore-submodules=<when>

忽略差异代中子模块的更改。<when>可以是“none”,“untracked”,“dirty”或“all”,这是默认设置。如果子模块包含未跟踪或已修改的文件,或者HEAD与超级项目中记录的提交不同,并且可用于覆盖ignoregit-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。

<tree-ish>

树对象的ID来区分。

--cached

根本不考虑磁盘上的文件

-m

默认情况下,记录在索引但未检出的文件被报告为已删除。该标志git diff-index表示所有未签出的文件都是最新的。

原始输出格式

“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. 到结肠。
  2. 模式为“src”; 000000如果创建或未合并。
  3. 空间。
  4. 模式为“dst”; 000000如果删除或未合并。
  5. 空间。
  6. sha1代表“src”; 0 {40}如果创建或未合并。
  7. 空间。
  8. sha1为“dst”; 0 {40}如果创建,不合并或“看工作树”。
  9. 空间。
  10. 状态,然后是可选的“分数”编号。
  11. 选项卡或NUL -z选项时使用。
  12. “src”的路径
  13. 使用选项卡时-z选项卡或NUL ; 只存在于C或R.
  14. “dst”的路径;只存在于C或R.
  15. 使用LF或NUL -z选项时,可以终止记录。

可能的状态字母是:

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

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

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

示例:

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

如果没有这个-z选项,带有“unusual”字符的路径名将按照配置变量的说明引用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. 单一路径,仅适用于“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/文件名。

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

  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)。
  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或git-show合并时的默认格式。还要注意,您可以-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”header,看起来像这样(当使用-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. 紧接着是两行文件/文件头--- a/file +++ b/file

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

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

@组合diff格式的块头中有(parents+ 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. 路径名(可能带有rename/copy信息);
  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,该记录将显示两个路径。

操作模式

您可以选择是完全信任索引文件(使用--cached标志),还是要求diff逻辑显示任何与stat状态不匹配的文件,因为它们“tentatively changed”。这两种操作的确非常有用。

缓存模式

如果--cached指定,它允许你问:

show me the differences between HEAD and the current index
contents (the ones I'd write using 'git write-tree')

例如,假设您已经在您的工作目录上工作,更新了索引中的一些文件并准备好提交。你想看看到底什么你要提交,而无需编写一个新的树对象,并比较这种方式,要做到这一点,你只是做

git diff-index --cached HEAD

例如:假设我已经重命名commit.cgit-commit.c,并且我已经完成了update-index在索引文件中使其生效。git diff-files根本不会显示任何内容,因为索引文件与我的工作目录匹配。但做一个git diff-index确实如此:

torvalds@ppc970:~/git> git diff-index --cached HEAD
-100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        commit.c
+100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        git-commit.c

你可以很容易地看到上述是重命名。

实际上,git diff-index --cached 应该完全等同于实际进行git write-tree和比较。除此之外,你只是想检查你的位置,这种情况要好得多。

因此,git diff-index --cached当你问自己“我已经标记了什么被提交了,以及与以前的树有什么不同”时,这样做基本上非常有用。

非缓存模式

“非缓存”模式采用不同的方法,并且可能更有用,因为它不能用git write-tree+ 来模拟git diff-tree。因此这是默认模式。非缓存版本会问这个问题:

向我展示HEAD和当前签出的区别
树 - 索引内容_and_不是最新的文件

这显然是一个非常有用的问题,因为它告诉你可以提交什么。再一次,输出与输出相匹配git diff-tree -r,但带有扭曲。

扭曲的是,如果某个文件与索引不匹配,我们就没有支持存储的东西,我们使用神奇的“全零”sha1来表明这一点。假设你已经编辑过kernel/sched.c,但实际上还没有完成git update-index- 没有与新状态关联的“object”,你会得到:

torvalds@ppc970:~/v2.6/linux> git diff-index --abbrev HEAD
:100644 100664 7476bb... 000000...      kernel/sched.c

即它表明树已经改变,并且kernel/sched.c不是最新的并且可能包含新的东西。全零的sha1意味着要获得真正的差异,您需要直接在工作目录中查看对象,而不是执行对象到对象的差异。

注意

和其他这种类型的命令一样,git diff-index实际上根本不会查看文件的内容。所以也许kernel / sched.c实际上并没有改变,只是你触及它而已。在任何一种情况下,都要注意你需要对它进行更新索引以使索引同步。

注意

您可以将文件混合在一起显示为“已更新”和“仍在工作目录中”。你总是可以知道哪个文件处于哪个状态,因为“已被更新”的文件显示有效的sha1,而“与索引不同步”的文件将始终有特殊的全零sha1。

Git

Git 是一个分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以 GPL 发布。最初目的是为更好地管理 Linux 内核开发而设计。

主页 https://git-scm.com/
源码 https://github.com/git/git
发布版本 2.14.3