我希望我的远程存储库拒绝任何包含包含选项卡的文件的推送,但前提是该文件属于某个类(基于文件名)。这可能吗?
我看了一下githooks中的update hook
,我认为这是正确的。
因此,简而言之,如果出现以下情况,则应拒绝推送:
*.cpp
,*.h
,CMakeLists.txt
)答案 0 :(得分:15)
您正在寻找update hook,每次更新时都会运行一次{{3}}。参数是ref的名称,旧对象名称(提交SHA1)和新对象名称。
所以,你真正需要做的就是检查新旧之间的差异,并确保它符合你的标准。当然,这并非完全直截了当,但它完全可以管理。这就是我要做的事情:
将以下脚本保存到.git/hooks/update
。
old=$2
new=$3
# that's a literal tab, because (ba)sh turns \t into t, not a tab
# make sure your editor doesn't expand it to spaces
git diff --name-only $old $new | egrep '(\.(cpp|h)$)|^CMakeLists.txt$' | xargs -d'\n' git diff -U0 $old $new -- | grep -q '^+.* ' && exit 1
列出了旧的和新的所有文件,所有期望的greps,获取它们的差异(上下文为零,因为我们不关心),以及添加行的greps(以+
开头)包含选项卡。 grep如果找到一个会退出成功,这将使&&
运行exit 1
,导致挂钩退出失败并中止更新!
请注意,这与您的要求略有不同 - 它会检查diff是否添加任何制表符。从长远来看,这可能更好;一旦你确定你现有的代码没问题,它就是一样的,除了更快,因为它不必搜索所有的内容。
答案 1 :(得分:3)
您可以设置pre-push hook,但这并不符合git发布机制的精神。
我宁愿选择:
答案 2 :(得分:1)
根据benprew's工作,这里有一个预脚本挂钩,如果添加了任何制表符,则会显示错误,以及相关的行号。将以下内容保存到pre-commit
。
(注意:.
是文件名。不应该是任何#!/bin/sh
if git rev-parse --verify HEAD 2>/dev/null
then
git diff-index -p -M --cached HEAD
else
:
fi |
perl -e '
my $found_bad = 0;
my $filename;
my $reported_filename = "";
my $lineno;
sub bad_line {
my ($why, $line) = @_;
if (!$found_bad) {
print STDERR "*\n";
print STDERR "* You have some suspicious patch lines:\n";
print STDERR "*\n";
$found_bad = 1;
}
if ($reported_filename ne $filename) {
print STDERR "* In $filename\n";
$reported_filename = $filename;
}
print STDERR "* $why (line $lineno)\n";
print STDERR "$filename:$lineno:$line\n";
}
while (<>) {
if (m|^diff --git a/(.*) b/\1$|) {
$filename = $1;
next;
}
if (/^@@ -\S+ \+(\d+)/) {
$lineno = $1 - 1;
next;
}
if (/^ /) {
$lineno++;
next;
}
if (s/^\+//) {
$lineno++;
chomp;
if (/ /) {
bad_line("TAB character", $_);
}
}
}
exit($found_bad);
'
扩展名
localhost
它不是完全您要求的内容,因为它没有进行任何文件检查,但希望无论如何都有帮助。