Cas*_*bel 24
你知道钩子 - 请阅读有关它们的文档!你可能想要的钩子是更新,每个ref运行一次.(预接收钩子在整个推动过程中运行一次)SO上已经有大量关于这些钩子的问题和答案; 根据你想要做什么,你可以找到有关如何在需要时编写钩子的指导.
为了强调这确实是可能的,来自文档的引用:
此挂钩可用于通过确保对象名称是提交对象来防止对某些引用的强制更新,该提交对象是旧对象名称所指定的提交对象的后代.也就是说,执行"仅限快进"政策.
它还可以用于记录old..new状态.
具体细节:
钩子为每个ref更新执行一次,并带有三个参数:
- 要更新的ref的名称,
- 存储在ref中的旧对象名称,
- 以及要存储在ref中的新对象名.
因此,例如,如果您想确保没有任何提交主题超过80个字符,那么一个非常基本的实现将是:
#!/bin/bash
long_subject=$(git log --pretty=%s $2..$3 | egrep -m 1 '.{81}')
if [ -n "$long_subject" ]; then
echo "error: commit subject over 80 characters:"
echo " $long_subject"
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
当然,这是一个玩具的例子; 在一般情况下,您将使用包含完整提交消息的日志输出,按提交将其拆分,并在每个单独的提交消息上调用验证代码.
这些已在评论中讨论/澄清; 这是一个总结.
更新挂钩每个ref运行一次.ref是指向对象的指针; 在这种情况下,我们讨论的是分支和标签,通常只是分支(人们不经常推送标签,因为它们通常仅用于标记版本).
现在,如果用户正在将更新推送到两个分支,即master和experimental:
o - o - o (origin/master) - o - X - o - o (master)
\
o - o (origin/experimental) - o - o (experimental)
Run Code Online (Sandbox Code Playgroud)
假设X是"坏"提交,即将使commit-msg挂钩失败的提交.显然我们不想接受推动掌握.所以,更新钩子拒绝了.但实验的提交没有错!更新钩子接受那个.因此,origin/master保持不变,但origin/experimental会更新:
o - o - o (origin/master) - o - X - o - o (master)
\
o - o - o - o (origin/experimental, experimental)
Run Code Online (Sandbox Code Playgroud)
预接收挂钩仅在开始更新refs之前运行一次(在第一次运行更新挂钩之前).如果你使用它,你必须导致整个推送失败,因此说因为主机上有一个错误的提交消息,你不知道如果他们的消息很好就不再相信实验的提交是好的!
你可以使用以下pre-receive钩子来完成它.正如其他答案所指出的那样,这是一种保守的,全有或全无的方法.请注意,它仅保护主分支,并且不对主题分支上的提交消息施加约束.
#! /usr/bin/perl
my $errors = 0;
while (<>) {
chomp;
next unless my($old,$new) =
m[ ^ ([0-9a-f]+) \s+ # old SHA-1
([0-9a-f]+) \s+ # new SHA-1
refs/heads/master # ref
\s* $ ]x;
chomp(my @commits = `git rev-list $old..$new`);
if ($?) {
warn "git rev-list $old..$new failed\n";
++$errors, next;
}
foreach my $sha1 (@commits) {
my $msg = `git cat-file commit $sha1`;
if ($?) {
warn "git cat-file commit $sha1 failed";
++$errors, next;
}
$msg =~ s/\A.+? ^$ \s+//smx;
unless ($msg =~ /\[\d+\]/) {
warn "No bug number in $sha1:\n\n" . $msg . "\n";
++$errors, next;
}
}
}
exit $errors == 0 ? 0 : 1;
Run Code Online (Sandbox Code Playgroud)
它要求推送中的所有提交在其各自的提交消息中的某处具有错误号,而不仅仅是提示.例如:
$ git log --pretty=oneline origin/master..HEAD 354d783efd7b99ad8666db45d33e30930e4c8bb7 second [123] aeb73d00456fc73f5e33129fb0dcb16718536489 no bug number $ git push origin master Counting objects: 6, done. Delta compression using up to 2 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (5/5), 489 bytes, done. Total 5 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (5/5), done. No bug number in aeb73d00456fc73f5e33129fb0dcb16718536489: no bug number To file:///tmp/bare.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'file:///tmp/bare.git'
假设我们通过将两个提交压缩在一起并推送结果来解决问题:
$ git rebase -i origin/master [...] $ git log --pretty=oneline origin/master..HEAD 74980036dbac95c97f5c6bfd64a1faa4c01dd754 second [123] $ git push origin master Counting objects: 4, done. Delta compression using up to 2 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 279 bytes, done. Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. To file:///tmp/bare.git 8388e88..7498003 master -> master