我正在尝试使用 git hook 来验证我团队的提交消息。
我已经配置了全局模板:
git.exe config --global commit.template .git/.gitmessage
现在我想创建 pre-commit 钩子以确保开发人员根据模板编写提交消息:
types: fix, feat, refactor, style, BREAKING CHANGE
<type>: <description>
[optional body]
[optional footer(s)]
如果页脚包含
(template-ignore)
,则挂钩应接受提交消息。
钩子应接受自动生成的分支合并提交(我不知道它是自动完成还是由钩子处理)。
我的最终目的是为我的团队生成一个标准,这样我就可以根据提交生成更改日志/发行说明。
我尝试使用默认的钩子并对其进行调整。
使用
pre-commit
或 commit-msg
钩子来验证共享团队的提交消息不是正确的工具。大多数 Git 挂钩都在开发人员系统上运行,这意味着它们可以被绕过,而且通常就像执行 --no-verify
一样简单。这不会留下任何痕迹,也无法禁用,这就是为什么 Git FAQ 建议不要这样做。此外,对用户强制执行此类挂钩会阻止用户执行有用的操作,例如创建修复或压缩提交或临时保存正在进行的工作。这些挂钩对于希望使用它们的用户来说可能很有价值,但它们不是有效的控制,不应该强加给用户。
还应该注意的是,Git 没有办法在用户系统上自动安装钩子,因为这是一个安全风险。因此,即使您将挂钩包含在存储库中,也无法强制安装它们。
如果您想验证提交消息,我建议在服务器端的
pre-receive
钩子或 CI 系统中执行此操作。这是一个你可以创建有效控制和验证事物的地方。我还建议将变更日志条目作为预告片而不是在提交摘要中包含,因为提交摘要通常应该解释与开发人员相关的更改,而这通常不是与最终用户相关的更改。这就是我们在前雇主那里所做的,效果非常好。
因此,考虑到这一点,您可以使用
Changelog
预告片执行类似的操作(将 BASE
和 HEAD
替换为 CI 系统中合适的提交):
git rev-list --format=%B BASE...HEAD | ruby -ropen3 -e '
def process(msg, commit)
out, st = Open3.capture2("git", "interpret-trailers", "--parse", stdin_data: msg, binmode: true)
raise "git failed" unless st.success?
saw_changelog = false
out.each_line do |line|
if line =~ /^Changelog: (.*)$/
saw_changelog = true
body = $1
if body == "none"
$stderr.puts "No changelog entry for #{commit}: ok"
elsif body =~ /^(fix|feat|refactor|style|BREAKING CHANGE): (.+)$/
$stderr.puts "Changelog entry passed for #{commit}: type #{$1}"
end
end
end
raise "No changelog for #{commit}"
end
data = nil
commit = nil
while line = gets
if line =~ /^commit ([0-9a-f]+)$/
process(data, commit) unless data.nil?
commit = $1
data = ""
else
data << line
end
end
process(data, commit)
'
如果您确实想要执行提交摘要版本(而不是预告片),那么您不需要
git interpret-trailers
调用,而可以只处理第一行。如何做到这一点留给读者作为练习。