为什么'git status'会忽略.gitattributes清理过滤器?

Oma*_*ohl 10 git gitattributes

我有一个.gitattributes清理过滤器,用于在提交之前删除文件中的所有注释.

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

$ cat .gitattributes
*   filter=cleancomments
Run Code Online (Sandbox Code Playgroud)

我有一个文件'test',其中包含以下内容(在存储库中提交):

This is a file with random content
Run Code Online (Sandbox Code Playgroud)

现在我对'test'进行修改并添加注释:

This is a file with random content
# and some comments
# like this
Run Code Online (Sandbox Code Playgroud)

git status 现在告诉我:

modified:   test
Run Code Online (Sandbox Code Playgroud)

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

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

对我来说真正神秘的是:

如果我这样做:

git add test
Run Code Online (Sandbox Code Playgroud)

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

tor*_*rek 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/cleaning-entry配对可能会很好,但似乎没有.


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

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