在 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 diff
?git 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年后同样的问题仍会存在。 ;-)