我正在使用Git for Windows(和TortoiseGit)。
我的目标是防止修改/添加至少有一个非UTF-8文件的提交。
{ git diff --name-only ; git diff --name-only --staged ; }
这是最好(正确和最简洁)的方法吗?{ git diff --name-only ; git diff --name-only --staged ; } | xargs -I {} bash -c "iconv -f utf-8 -t utf-16 {} &>/dev/null || echo {} - is non-UTF8!"
如果我在我的存储库根文件夹中启动Git Bash - 它可以工作(显示每个非UTF-8文件)。所以我将.git/hooks/pre-commit.sample
重命名为.git/hooks/pre-commit
并复制粘贴上面的代码。在提交更改后,TortoiseGit内部没有任何特殊显示提交gui窗口。所以看起来预提交挂钩不能正常工作。所以任何帮助都表示赞赏。
您现有的解决方案可能已足够。虽然这不是100%正确:这是剩下的问题,所有这些都是次要问题,你可以稍后(如果有的话)在你的闲暇时解决:
git diff ... --staged
(或--cached
),因为Git将提交的是索引/登台区域中的任何文件,git diff
将它与HEAD
提交中的内容进行比较,并告诉你那里有什么不同。如果索引中的文件副本与HEAD
中的文件副本不同,则应检查索引副本。git diff-index --cached
,以便不遵守任何用户的git diff
配置。也就是说,git diff-index
是Git中的一个管道命令,这意味着它的目的是用于其他计算机程序:它只能基于参数以完全可预测的方式运行,而不是基于任何git config
设置。但是如果你自己这样做,并且你配置git diff
这样就会破坏你自己对git diff
的使用,那么,这是你自己的错。 :-)--diff-filter
在此处排除已删除的文件。否则,您的检查器将始终失败(因为iconv
将无法读取已删除的文件)。iconv
将从工作树中读取文件。正如我在第一个要点中指出的那样,Git将承诺上演的内容,而不是工作树中的内容。作为一个例子 - 在TortoiseGit中可能会或可能不会 - 考虑如果你这样做会发生什么:
$ git checkout master
$ printf '\300\300\300' > badfile # put bad non-UTF-8 crud into file
$ git add badfile # copy file into index
$ echo 'good data' > badfile # replace work-tree contents
$ git commit
这个提交将提交错误的内容 - \300
的三个字节,没有换行符 - 在索引中,但你的预提交钩子将在好文件的内容上运行iconv -f utf-8 -t utf-16
,读取good data
,即当然好。
要解决此问题,您的预提交过滤器必须从索引中提取要提交的每个文件的数据。你如何做到这一点取决于你。最简单(但也许最慢)的方法是使用git checkout-index
将整个索引内容提取到临时工作区。一个更好的方法可能是将每个in-index(in-staging-area)路径名转换为有效的索引说明符(即path/to/file
变为:path/to/file
)并使用git cat-file -p $specifier | iconv ...
扫描每个。但所有这些都是相当低效的,特别是在Windows上。为了提高效率,您可能希望编写一个Python脚本,该脚本使用git cat-file --batch
一次性提取它们,并在那里进行格式检查。