Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows GIT pre-commit钩子,它在修改/添加的文件中搜索非UTF-8编码(如果找到任何,则拒绝提交)_Windows_Bash_Git_Git Bash_Pre Commit Hook - Fatal编程技术网

Windows GIT pre-commit钩子,它在修改/添加的文件中搜索非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 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!"
    
    这是最好的(正确且最简洁的)方法吗

  • 搜索非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
    ,并复制粘贴了上面的代码。提交更改后,在Ortoisegit提交gui窗口中不会显示任何特殊内容。看来预提交钩子没有正常工作

  • 如果存在任何非UTF-8文件,则拒绝提交:显示所有非UTP-8文件后,应拒绝提交。但我不知道如何做到这一点(显示一些退出代码-但如何?)

因此,任何帮助都是非常感谢的。

因此答案是(thx to和great thx to,感谢他的有用注释):


此代码迭代所有在提交中更改的文件(删除的文件除外,即添加、修改、复制和重命名的文件),并检查是否存在任何非UTF8文件。将列出所有找到的文件并中止提交。

您现有的解决方案可能已经足够。但这并不是100%正确:以下是剩余的问题,所有这些都是小问题,您可以稍后(如果有)在空闲时解决:

  • 您只需要
    git diff--staged
    (或
    --cached
    ),因为Git将提交索引/staging区域中的任何文件,而
    Git diff
    将其与
    头中的内容进行比较,并告诉您有什么不同。如果索引中的文件副本与
    标题中的文件副本不同,则应检查索引副本

  • 从技术上讲,最好在这里使用
    git-diff-index--cached
    ,这样就不会遵守任何用户的
    git-diff
    配置。也就是说,
    git diff index
    是git中的一个管道命令,这意味着它的目标是从其他计算机程序中使用:它以完全可预测的方式运行,仅基于参数,而不基于任何
    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中使用更快,尽管我必须进行测量才能确定。