编辑:

编辑:

在 git 中提交配置文件之前,我使用过滤器删除注释:

$ cat .git/config
[filter "stripcomments"]
clean = "stripcomments"

$ cat .git/info/attributes 
/etc/* filter=stripcomments

我还有 shell 提示,如果有任何未提交的文件,它会改变颜色。这是我的相关部分.zshrc

[[ -n "$(git status --porcelain 2> /dev/null | tail -n1)" ]] && git_c=220 || git_c=34

我遇到的问题是,当我通过添加注释来更改文件时,我的过滤器会删除注释,并且用于 git 目的的文件应该保持不变。我可以验证这git diff没有什么区别。但git status显示文件已更改,因此我的 shell 显示黄色提示,表示未提交的更改。

我必须用什么来解决这个问题?

编辑:

更糟糕的是,当我这样做时git status,它会显示修改后的文件。当我这样做时,git diff它没有显示任何变化。当我这样做时git commit,它告诉我没有什么可承诺的。

换句话说,git status显示更改的文件,但我无法提交。

答案1

git status如果您更改注释而不更改文件大小,例如更改一个字符,或者有两个单行注释并切换它们,任何不会更改文件总长度或过滤结果的内容,都会按预期工作。

对于相同大小的修改(mtime)文件,git status读取其内容,运行过滤器并进行比较。只要评论的变化被过滤掉,就没有变化。

但是,如果文件大小不同,则git status根本不运行过滤器,甚至不查看文件内容。仅文件大小的变化就足以使git status文件被视为已更改。

比较文件大小而不是文件内容是一种常见的优化。在这种情况下,这对你不利。而且似乎没有关闭它的选项。

core.checkStat = minimal一个几乎可以禁用所有功能除了文件大小检查。所以这是一个死胡同。如果还有与此问题相关的其他选项,我找不到。

所以我没有适当的解决方案来改变git status行为。

您可能必须完全切换到不同的命令(运行git diffgit commit --dry-run否则它实际上不会提交?)。这些工具运行过滤器(然后不执行任何操作),因为它们实际上必须查看文件内容来比较/提交更改。否则,运行git add以更新 git 中的缓存文件大小? (不涉及提交)

另一个(奇怪的)选项是强制文件大小问题。对于文本文件,您只需附加注释,然后截断文件以始终具有相同的大小。因此文件大小永远不会改变,并且git status必须为您检查文件内容。

这将git status适合您的用例,但几乎不实用。


更激进的方法是git自我修复。

diff --git a/read-cache.c b/read-cache.c
index 35e5657877..4e087ca3f5 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -213,7 +213,7 @@ int match_stat_data(const struct stat_data *sd, struct stat *st)
 #endif

        if (sd->sd_size != (unsigned int) st->st_size)
-               changed |= DATA_CHANGED;
+               changed |= MTIME_CHANGED;

        return changed;
 }

这会假装大小变化仅仅是时间变化(然后稍后开始文件内容比较)。但是,这仅适用于您本地,而且风险很大。毕竟,这个函数负责你的 git 存储库的完整性,我根本无法判断这样的更改是否安全。

如果您执行类似的操作,您应该将其命名为 Frankengit,并确保它根本无法修改您的存储库(至少添加--no-optional-locks到状态命令中)。


同样的问题,9年前问过:

Git 邮件列表讨论:

显然没有任何结果,但如果您关心此功能,无论如何您都应该在邮件列表中再考虑一次。否则9年后同样的问题仍会存在。 ;-)

相关内容