我希望我的远程存储库拒绝任何包含包含选项卡的文件的推送,但前提是该文件属于某个类(基于文件名)。那可能吗?
我看了一点update hook
in githooks,我认为这是正确的。
简而言之,如果出现以下情况,则应拒绝推送:
- 有一个列出类型的文件 (
*.cpp
,*.h
,CMakeLists.txt
) - 包含一个或多个制表符。
哦哦,这个问题好像漏掉了。希望你还在外面,埃斯本!
您正在寻找一个更新钩子,它为每个更新的 ref 运行一次。参数是 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 如果找到一个则退出成功,这将让&&
run exit 1
,导致钩子退出失败并中止更新!
请注意,这与您的要求略有不同 - 它检查差异是否添加了任何制表符。从长远来看,这可能会更好;一旦你确定你现有的代码没问题,它就是同样的事情,除了更快,因为它不必搜索所有内容。
你可以设置一个pre-push hook,但这并不真正符合 git 发布机制的精神。
我宁愿选择:
根据benprew 的工作,这里有一个 pre-script 钩子,如果添加了任何制表符,则会显示错误,以及相关的行号。将以下内容保存到.git/hooks/pre-commit
.
(注意: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);
'
它不完全符合您的要求,因为它不进行任何文件名检查,但希望无论如何它都会有所帮助。