Windows GIT pre-commit钩子,它在修改/添加的文件中搜索非UTF-8编码(如果找到任何,则拒绝提交)
我正在使用Git for Windows(和TortoiseGit) 我的目标是防止在修改/添加的文件中至少有一个非UTF-8文件的提交Windows GIT pre-commit钩子,它在修改/添加的文件中搜索非UTF-8编码(如果找到任何,则拒绝提交),windows,bash,git,git-bash,pre-commit-hook,Windows,Bash,Git,Git Bash,Pre Commit Hook,我正在使用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
- 枚举修改/添加的文件:我发现了以下代码
{ 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!"
- 搜索非UTF-8文件:我找到了以下代码
{ git diff --name-only ; git diff --name-only --staged ; }
如果我在我的存储库根文件夹中启动Git Bash,它就会工作(显示每个非UTF-8文件)。因此,我将{ 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/hooks/pre-commit.sample
,并复制粘贴了上面的代码。提交更改后,在Ortoisegit提交gui窗口中不会显示任何特殊内容。看来预提交钩子没有正常工作.git/hooks/pre-commit
- 如果存在任何非UTF-8文件,则拒绝提交:显示所有非UTP-8文件后,应拒绝提交。但我不知道如何做到这一点(显示一些退出代码-但如何?)
此代码迭代所有在提交中更改的文件(删除的文件除外,即添加、修改、复制和重命名的文件),并检查是否存在任何非UTF8文件。将列出所有找到的文件并中止提交。您现有的解决方案可能已经足够。但这并不是100%正确:以下是剩余的问题,所有这些都是小问题,您可以稍后(如果有)在空闲时解决:
- 您只需要
(或git diff--staged
),因为Git将提交索引/staging区域中的任何文件,而--cached
将其与Git diff
头中的内容进行比较,并告诉您有什么不同。如果索引中的文件副本与
标题中的文件副本不同,则应检查索引副本
- 从技术上讲,最好在这里使用
,这样就不会遵守任何用户的git-diff-index--cached
配置。也就是说,git-diff
是git中的一个管道命令,这意味着它的目标是从其他计算机程序中使用:它以完全可预测的方式运行,仅基于参数,而不基于任何git diff index
设置。但是,如果您是为自己这样做的,并且您配置了git config
,从而中断了自己对git diff
的使用,那么,这是您自己的错。:-)git diff
<> >您也可以考虑使用<代码> -DIFF筛选器< /代码>来排除已删除的文件。否则,您的检查程序在删除时将始终失败(因为
iconv
将无法读取删除的文件)
iconv
将从工作树中读取文件。正如我在第一个要点中指出的,Git将提交上演的内容,而不是工作树中的内容作为一个例子,在TurtoSeigIT中可能或不可能考虑如果你这样做会发生什么:
$ 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
,读取好数据,这当然是好的
要解决此问题,您的预提交筛选器必须从要提交的每个文件的索引中提取数据。你该怎么做取决于你自己。最简单(但可能最慢)的方法是使用git checkout index
将整个索引内容提取到临时工作区。更好的方法可能是将索引(在暂存区)中的每个路径名转换为有效的索引说明符(即,path/to/file
变成:path/to/file
),并使用git cat file-p$specifier | iconv…
扫描每个路径。但所有这些都将相当低效,尤其是在Windows上。为了提高效率,您可能需要编写一个Python脚本,该脚本使用git cat file--batch
一次将它们全部提取出来,并在那里执行格式检查。:以非零状态退出此脚本会导致git commit命令在创建提交之前中止。所以:{echo{}-是非UTF8!>&2;退出1;}
@phd&2
部分为我显示了一个错误。无论如何,{echo{}-是非UTF8!退出1;}
在TortoiseGit提交gui窗口中工作正常(显示我需要的所有信息并中止提交)。谢谢。最好的方法是只使用cat文件--批处理它们,git diff index--缓存@awk'$4~/[^0]/{print$4}'| git cat文件--批处理iconv-f utf-8-t utf-8-o/dev/null
。我承认我没有看完你的最后一句话。我认为这应该是第一件事,因为这将是最快的,99%以上的时间就足够了。如果需要的话,返回并挖掘出可以单独完成的文件。@jthill:这是一个正确的观点。使用iconv可能也比在Python中使用更快,尽管我必须进行测量才能确定。