使用更新挂钩
您了解钩子 - 请阅读有关它们的 documentation!您可能想要的钩子是更新,每个参考运行一次。 (预接收钩子在整个推送过程中运行一次)关于这些钩子的问题和答案已经很多了。取决于你想做什么,如果你需要的话,你可能会找到关于如何编写钩子的指导。
为了强调这确实是可能的,引用文档中的一句话:
此钩子可用于防止强制更新某些引用,方法是确保对象名称是提交对象,该提交对象是由旧对象名称命名的提交对象的后代。也就是说,强制执行“仅快进”策略。
它也可以用来记录 old..new 状态。
以及细节:
钩子对每个要更新的 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
当然,这是一个玩具示例;在一般情况下,您会使用包含完整提交消息的日志输出,将其拆分为每个提交,然后在每个单独的提交消息上调用您的验证码。
为什么需要更新挂钩
这已在 cmets 中讨论/澄清;这是一个摘要。
更新挂钩每个 ref 运行一次。 ref 是指向对象的指针;在这种情况下,我们谈论的是分支和标签,通常只是分支(人们不经常推送标签,因为它们通常只是用于标记版本)。
现在,如果用户将更新推送到两个分支,主分支和实验分支:
o - o - o (origin/master) - o - X - o - o (master)
\
o - o (origin/experimental) - o - o (experimental)
假设 X 是“错误的”提交,即提交-msg 钩子失败的提交。显然,我们不想接受对 master 的推动。所以,更新钩子拒绝了。但是实验上的提交并没有错!更新钩子接受那个。因此,origin/master 保持不变,但 origin/experimental 得到更新:
o - o - o (origin/master) - o - X - o - o (master)
\
o - o - o - o (origin/experimental, experimental)
pre-receive 钩子只运行一次,就在开始更新 refs 之前(在第一次运行更新钩子之前)。如果你使用它,你将不得不导致整个推送失败,因此说因为 master 上有一个错误的提交消息,你不知何故不再相信实验上的提交是好的,即使它们的消息很好!