Git合并GitHub PR时pre-receive钩子Jira校验失败求助
解决Git pre-receive钩子在GitHub PR合并时的校验失败问题
问题根源
GitHub合并Pull Request时,会自动生成新提交(比如默认的合并提交,或squash合并后的单一提交),这些提交的默认信息通常不包含Jira工单编号或[NA]标签,且会被你的pre-receive钩子纳入校验范围,导致报错。
解决方案
针对合并提交的特性,可通过以下两种方案解决:
方案1:跳过合并提交的校验
合并提交的特征是拥有两个或以上父节点,通过检查提交的父节点数量识别它,直接跳过校验。修改后的钩子代码如下:
set -e zero_commit='0000000000000000000000000000000000000000' msg_regex='(^\[NA\])|([A-Z]+-[0-9]+)' branch_regex='[A-Z]+-[0-9]+' na_tag="[NA]" while read -r oldrev newrev refname; do branch=${refname#refs/heads/} ticket_in_branch=$(echo "${branch}" | grep -oE "$branch_regex" || echo "") # 忽略分支删除操作 [ "$newrev" = "$zero_commit" ] && continue # 确定需要校验的提交范围 [ "$oldrev" = "$zero_commit" ] && range="$newrev" || range="$oldrev..$newrev" for commit in $(git rev-list "$range" --not --all); do # 判断是否为合并提交(父节点数≥2) parent_count=$(git show --no-patch --format=%p "$commit" | wc -w) if [ "$parent_count" -ge 2 ]; then echo "跳过合并提交 ${commit} 的校验" continue fi ticket_in_commit=$(git log --max-count=1 --format=%B "$commit" | grep -oE "$msg_regex" || echo "") if [ "$ticket_in_commit" = "$ticket_in_branch" ]; then echo "提交 ${commit} 已包含Jira工单编号或[NA]: ${ticket_in_commit}" else if [ -z "$ticket_in_branch" ] && [ "$ticket_in_commit" = "$na_tag" ]; then echo "提交 ${commit} 已包含[NA]标签: ${na_tag}" else echo "MESSAGE" echo "ERROR:" echo "ERROR: 推送被拒绝,提交 ${commit} (分支 ${branch})" echo "ERROR: 缺少JIRA工单编号(例如: '[AB-1234] 提交信息')或[NA]标签,或工单编号与分支不匹配" echo "ERROR:" echo "ERROR: 请修正提交信息后重新推送。" echo "ERROR" exit 1 fi fi done done
方案2:要求合并提交信息符合规则
如果需要严格管控合并提交的信息,可调整正则表达式,允许提交信息任意位置出现Jira编号或[NA],同时在合并PR时手动确保提交信息符合规则:
# 修改正则表达式,匹配任意位置的[NA]或Jira编号 msg_regex='(\[NA\])|([A-Z]+-[0-9]+)'
合并PR时,编辑提交信息加入符合规则的内容(比如将PR标题设置为[AB-1234] 合并功能分支),即可通过钩子校验。
补充说明
- 若使用squash合并,GitHub会生成新提交,默认信息是PR所有提交的汇总,合并时手动编辑提交信息加入Jira编号或
[NA]即可通过校验。 - 若仅需管控普通开发提交,方案1是最直接的解决方式,避免合并操作被拦截。
内容的提问来源于stack exchange,提问作者Frendom
相关产品推荐
相关产品推荐

