有没有人知道一个好的git钩子会在提交时检查二进制文件并抛出错误?我试图阻止二进制文件被提交到我的存储库,但有时人们会犯错误。
谢谢!
答案 0 :(得分:7)
我不知道现有的钩子,但是git已经附带了一个钩子来检查添加“非ascii名称”,作为一个示例预提交钩子。这可能已经在您现有的git存储库中.git/hooks/pre-commit.sample
。
使用该挂钩作为模板并考虑"How to determine if Git handles a file as binary or as text?"的答案,您可以执行以下操作(请参阅"git's semi-secret empty tree"了解EMPTY_TREE
的来源):
#! /bin/sh
stop_binaries=$(git config --get hooks.stop_binaries)
exec 1>&2
if [ "$stop_binaries" = true ]; then
EMPTY_TREE=$(git hash-object -t tree /dev/null)
# or: EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904
if git diff --cached --numstat $EMPTY_TREE | grep -e '^-' >/dev/null; then
echo Error: commit would add binary files:
git diff --cached --numstat $EMPTY_TREE | grep -e '^-' | cut -f3-
exit 1
fi
fi
这使用git diff --cached
来查看将要提交的内容,将其与初始空树进行比较。请注意,它将拒绝提交已存在(但未更改)的二进制文件;要使其仅拒绝新的或更改的二进制文件,请从非ascii-names挂钩添加against=
逻辑。要仅拒绝 new 二进制文件,也要添加--diff-filter=A
参数。
如果您愿意,可以使用其他错误消息文本。你可以反转测试(而不是断言“停止二进制”,使其默认停止,你必须设置“allowbinaries”来添加二进制文件),等等。当然你可以允许特定的目录充满二进制文件,或者其他,通过对diff-index输出进行额外的过滤。
答案 1 :(得分:2)
无耻的插件,但我wrote a pre-receive hook可以更智能地执行此操作。搜索后可以通过库存Git找到没有任何功能的可配置方式,而无需安装更大的Git管理系统。
答案 2 :(得分:0)
我们对Git回购有类似的要求。我们不希望允许非常大或二进制文件被意外检查,因为它们可以使回购膨胀并且很难从历史中删除。坦率地说,我很惊讶这样的钩子并不是所有Git用户的要求。我们希望我们在客户端,以便用户立即知道他们犯了错误。我们还希望允许用户在确定应该提交文件时覆盖挂钩。
为了测试二进制文件,我只使用了Perl的-B检查。我选择使用预提交钩子。要覆盖挂钩,我们只需打印提醒,告诉用户使用'--no-verify'重新运行提交。
最大文件大小是任意的,并在脚本中设置。您可以将其设置为适合您情况的任何内容。
您还会注意到,这只会检查正在添加(未修改)的文件,因为我们不希望每次修改大型或二进制文件时钩子都会成为麻烦。如果你想更严格,你可以改变diff-filter使用'ACM'(添加,复制或修改)。
#!/usr/bin/perl
# The hook should exit with non-zero status after issuing an appropriate
# message if it wants to stop the commit.
use strict;
use warnings;
my $file;
my $MAX_SIZE = 100000; # Limit files to 100KB
# Only check binary and file size when files are added otherwise users
# get an error every time they modify they file. This has the dissadvantage
# of not catching if a file grows too large after the initial commit
#
# Get list of added files only (i.e. new files)
my @new_file_list = `git diff --cached --name-only --diff-filter=A`;
foreach $file (@new_file_list)
{
chomp($file);
# Check if file is binary
if (-B $file)
{
print STDERR "WARNING: $file is binary.\n";
print STDERR "Please check with repo owner before committing binary files.\n";
print STDERR "To bypass this warning re-run your commit with the '--no-verify' option\n";
exit 1;
}
# Check if file is very large
if (-s $file > $MAX_SIZE)
{
print STDERR "WARNING: $file is greater than $MAX_SIZE bytes.\n";
print STDERR "Please check with repo owner before committing very large files.\n";
print STDERR "To bypass this warning re-run your commit with the '--no-verify' option\n";
exit 1;
}
}