12

我有一个.gitattributes clean 过滤器,可以在提交之前从文件中删除所有评论。

$ cat .git/config
[filter "cleancomments"]
    clean = "grep -v '^#'"

$ cat .gitattributes
*   filter=cleancomments

我有一个包含以下内容的文件“测试”(在存储库中提交):

This is a file with random content

现在我对“测试”进行修改并添加注释:

This is a file with random content
# and some comments
# like this

git status现在告诉我:

modified:   test

但是git diff是空的(应该如此)。

我并不完全清楚为什么 git status 不使用过滤器来决定文件是否已被修改,但我认为这就是它的实现方式。

对我来说真正神秘的是:

如果我这样做:

git add test

然后突然文件'test'不再被标记为已修改并且它没有出现在git索引中。为什么是这样?

4

1 回答 1

7

git add将文件添加到索引1但首先通过任何所需的过滤器运行它。

该索引包含文件的磁盘名称和“真实名称”(它的 git 哈希作为“blob”)以及目录stat值和一对 git 哈希值(原始和过滤),以及一些其他需要的位和 bobs。一旦add-ed,git status可以从索引数据中得知该文件现在在索引中是“最新的”,并且索引本身在存储库中是最新的,因为 blob 的哈希与HEAD提交哈希匹配。

但是,如果您再修改文件,一些关键stat数据会发生变化,使 git 认为索引已过期,并且git status会再次认为它需要git add-ed。2

这里的总体思路似乎是git status不写任何东西(甚至是索引)。如果git update-index --refresh更新 work-dir/cleaned-entry 配对可能会很好,但似乎没有。


1更准确地说,git add计算散列——因此是 repo 中的“真实名称”——然后当且仅当它不存在时才将对象添加到 repo。哈希值现在是已知的,可以根据需要存储在索引中。在进行过滤和散列之前,散列值是未知的,即git status不知道它。

2--assume-unchanged如果你使用和/或之类的东西,这里会有更多的微妙之处core.ignorestat

于 2013-11-06T10:05:50.437 回答