这是正常的(尽管令人沮丧的终端问题令人沮丧)。
git status 所做的是运行 两个 git diffs。
第一个差异很简单。它只是将HEAD 提交与索引进行比较。此处显示的任何差异都是“为提交暂存的更改”:索引中的文件与当前提交中的文件不同,因此有一些新的和不同的东西可以提交。
第二个差异比较棘手,因为 Git 进行了优化。
原则上,第二个差异很简单:它将索引与工作树进行比较。此处显示的任何差异都是“未为提交暂存的更改”,即您可以git add 将文件复制从工作树,到索引,替换索引中的任何先前版本。
但是,这里出现了“优化”以及它与 EOL 转换交互的方式(以及清洁过滤器,如果您使用这些过滤器)。繁荣,现在一切都变得复杂了。 :-)
当您设置任一一个干净的过滤器或 EOL转换(或两者)时,Git 会进行此清理(或转换,这基本上只是一个预编程的表单清理)在您运行 git add 以将文件从工作树复制到索引中时。这有两个棘手的含义:
- 索引中的文件确实,字面上,不匹配工作树中的文件,然而,此时 Git 应该声称它确实 .
- Git 不知道,或者在这一点上甚至关心,清理对文件做了什么。对 Git 来说重要的是索引版本“已知是干净的并且与工作树版本匹配”,因为,好吧,您刚刚添加了它,它必须是干净的并且匹配工作-树版本。
(我应该在这里提到另一个推论,即:当 Git 从索引到工作树中提取文件时,它会应用任何“脏”涂抹过滤器或 EOL 转换。这意味着工作树文件与索引版本不同,然而,因为 Git 刚刚提取它,它应该被视为“干净”——或者至少,索引 = 工作树——就像你git add它,它在进来的时候被清理了。)
Git 对 index-and-work-tree 的主要优化是保存 stat data,尤其是 mtime(修改时间)时间戳,以便它可以判断您是否已触及工作树版本自上次git add 以来的文件。如果保存的时间戳和其他统计数据都匹配,Git 可以假设工作树版本是“干净的”。
(文件系统stat操作很慢,所以还有一个优化:Git将目录的stat数据保存在索引中,可以跳过stat-ing 内的文件如果目录 mtime 本身匹配,则目录。幸运的是,这并没有在这里咬你。它对于未跟踪的文件特别有用,使用相对较新的“未跟踪缓存”。不是很相关,只是一个有趣的旁注。)
除此之外,使用 mtime 还有一个问题。详情请见https://www.kernel.org/pub/software/scm/git/docs/technical/racy-git.txt。
所有这一切的简短版本是,有时git status 故意撒谎。但是,一旦您 git added 文件,如果它没有显示为“暂存提交”,则文件的“清理”版本是相同的作为HEAD(当前)提交中的那个。
您可能想在此处尝试git update-index --refresh。或者,当然,您可以git add 看似修改过的文件,这可以解决问题,但很烦人。