Git
简体中文 ▾ Topics ▾ Latest version ▾ git-diff-files last updated in 2.43.0

名称

git-diff-files - 对比工作区和索引中的文件

概述

git diff-files [-q] [-0 | -1 | -2 | -3 | -c | --cc] [<common-diff-options>] [<path>…​]

描述

比较工作区和索引中的文件。 当指定路径时,只比较那些命名的路径。 否则就比较索引中的所有条目。 输出格式与 git diff-indexgit diff-tree 的相同。

选项

Warning

Missing zh_HANS-CN/diff-options.txt

See original version for this content.

-1 --基地
-2 --ours
-3 --theirs
-0

分别与 “基础” 版本、“我们的分支” 或 “他们的分支” 进行比较。 有了这些选项,合并后的条目的差异就不会显示。

默认是针对我们的分支 (-2) 和干净的解决路径进行差异比对。 可以给出选项 -0 来省略未合并的条目的差异输出,只显示 "Unmerged"。

-c
--cc

这将比较第二阶段(我们的分支)、第三阶段(他们的分支)和工作区文件,并输出一个综合的差异,类似于 diff-tree 显示带有这些标志的合并提交。

-q

即使对不存在的文件也保持沉默

原始输出格式

"git-diff-index","git-diff-tree","git-diff-files" 和 "git diff --raw" 的原始输出格式非常相似。

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

git-diff-index <tree-ish>

比较 <文件树> 和文件系统上的文件。

git-diff-index --cached <文件树>

比较 <文件树> 和索引。

git-diff-tree [-r] <文件树1> <文件树2> [<模式>…​]

比较由两个参数传递的文件树。

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

compares the index and the files on the filesystem.

"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. "src"(源文件)的模式;如果是新建或是未合并的,则为 000000。

  3. 空格。

  4. "dst"(目标文件)的模式;如果被删除或未合并则为 000000。

  5. 空格。

  6. "src"(源文件)的 sha1 值;如果为新建或未合并则为 0{40}。

  7. 空格。

  8. sha1 for "dst"; 0{40} if creation, unmerged or "look at work tree".

  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

Without the -z option, pathnames with "unusual" characters are quoted as explained for the configuration variable core.quotePath (see git-config[1]). Using -z the filename is output verbatim and the line is terminated by a NUL byte.

合并的差异格式

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

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

  2. there are more "src" modes and "src" sha1

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

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

  5. 以制表符分隔的文件路径名

For -c and --cc, only the destination or final path is shown even if the file was renamed on any side of history. With --combined-all-paths, the name of the path in each parent is shown followed by the name of the path in the merge commit.

以下为带 -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 生成补丁文本

Running git-diff[1], git-log[1], git-show[1], git-diff-index[1], git-diff-tree[1], or git-diff-files[1] with the -p option produces patch text. You can customize the creation of patch text via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables (see git[1]), and the diff attribute (see 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 <模式>,<模式>

    The mode <mode>,<mode>..<mode> line appears only if at least one of the <mode> is different from the rest. Extended headers with information about detected contents movement (renames and copying detection) are designed to work with diff of two <tree-ish> and are not used by combined diff format.

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

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

    类似于传统的 "统一" 差异格式的双行头,/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。

The extra NUL before the preimage path in renamed case is to allow scripts that read the output to tell if the current record being read is a single-path record or a rename/copy record without reading ahead. After reading added and deleted lines, reading up to NUL would yield the pathname, but if that is NUL, the record will show two paths.

GIT

属于 git[1] 文档

scroll-to-top