首页 > 解决方案 > 了解 git diff 的作用

问题描述

我从手册页中读到git diff它应该返回“工作树中的更改尚未为下一次提交暂存”。如果我了解工作树是什么(它应该是您的本地 git repo 工作文件夹),当我将一个新文件添加到我的工作目录时,我应该会看到它返回git diff,但它什么也没返回。我没有得到什么?

标签: git

解决方案


这与大小无关。它与 git 如何“看到”以及您要求的区别有关。

  • 首先,有三个地方:HEAD(最近的提交)、索引(你要做什么add)和工作树。所以有两个“简单的差异”命令:

    • git diff询问索引和工作树之间的差异。
    • git diff --cached询问 HEAD 和 index 之间的差异。
  • 其次,就 git 而言,HEAD 中不存在的内容或索引不存在;它是“未跟踪的”。

如果跟踪文件(它在索引或 HEAD 中),则工作树中但不在索引中的更改是unstaged。但是如果一个文件没有被跟踪,那么工作树中的变化就不会被跟踪;它们还没有达到未上演的水平,而且它们不会处于任何一种差异中。

好的。所以当你第一次创建一个文件时,不管它有没有大小,它根本不在 git 的权限范围内(它是未跟踪的),所以它不是任何差异的一部分:

$ touch Z # this one has no size
$ echo testing > ZZ # this one has size
$ git diff # (crickets...)
$ git diff --cached # (crickets...)

然后当你add那个文件时,现在 git 知道它(它被跟踪)。索引和工作空间之间仍然没有差异,因为索引与工作空间相同;您只是将这些文件从后者复制到前者!但是现在 HEAD 和索引之间确实存在差异:

$ git add .
$ git diff # (crickets...)
$ git diff --cached
diff --git a/Z b/Z
new file mode 100644
diff --git a/ZZ b/ZZ
new file mode 100644

好的,现在这些文件git 的监督下,因为它们在索引中。因此,现在如果我们对其中一个进行更改(在工作树中),索引和工作树之间存在差异(未分级):

$ echo testing2 >> ZZ
$ git diff
diff --git a/ZZ b/ZZ
--- a/ZZ
+++ b/ZZ
@@ -1 +1,2 @@
 testing
+testing2

反过来也是如此。为了说明我的意思,我将添加并提交所有内容;现在没有简单的差异,正如预期的那样:

$ git add .
$ git commit -m'xxxx'
$ git diff # (crickets...)
$ git diff --cached # (crickets...)

现在,我将从索引中删除ZZ,使用rm,从 HEAD 中删除,使用commit

$ git rm --cache ZZ
rm 'ZZ'
$ git commit -m'removed'

现在,索引和工作树之间再一次没有区别,即使文件 ZZ 仍在工作树中:

$ git diff # (crickets...)
$ ls
Z   ZZ

那是因为,由于 ZZ 不再在 HEAD 或 worktree 中,它再次未被跟踪;它再次不在 git 的权限范围内。


推荐阅读