必须在服务端 pre-receive 钩子中校验 commit message 是否含有效 Jira 工单号(如 PROJ-123),因其不可绕过;本地 pre-commit 仅作体验优化,可被 --no-verify 跳过。

要让 Git 在提交前就拦截不合规的 commit 信息(比如缺少有效 Jira 工单号),核心是利用 pre-commit 钩子做本地校验,再配合 pre-receive 钩子在服务端做最终把关。仅靠客户端钩子无法真正“禁止”,因为可被绕过(如用 git commit --no-verify);必须服务端介入才具备强制力。
一、本地 pre-commit 拦截(开发体验层)
在项目根目录的 .git/hooks/pre-commit 中写入检查逻辑:
- 提取当前 commit 的 message(用
git log -1 --pretty=%B HEAD或从git rev-parse --verify HEAD获取暂存区内容) - 用正则匹配 Jira 格式,例如
[A-Z]+-\d+(如PROJ-123、FEAT-456),注意排除常见误匹配(如邮箱、URL 中的连字符) - 若未匹配到有效工单号,输出明确提示(如
"Commit message must contain a valid Jira ticket (e.g., PROJ-123)")并exit 1 - 确保脚本有执行权限:
chmod +x .git/hooks/pre-commit
⚠️ 注意:此步骤可提升协作意识,但不能替代服务端控制。
二、服务端 pre-receive 钩子拦截(强制执行层)
这是真正“禁止推送”的关键。需在 Git 服务器(如自建 GitLab、Gitea 或裸仓库)的 hooks/pre-receive 文件中部署:
- 该脚本会在每次
git push时被调用,接收 stdin 输入的oldref newref refname三元组 - 对每个即将引入的新 commit(
git rev-list $oldref..$newref),逐条提取 message:git log -1 --pretty=%B $commit - 对每条 message 执行与 pre-commit 相同的 Jira 号正则校验
- 任一 commit 不达标,立即
echo "ERROR: Commit $commit lacks valid Jira ticket"并exit 1,整次推送将被拒绝
✅ 优势:不可绕过,所有推送都经过校验;适合团队统一策略。
三、配套建议(提升可用性)
避免规则变成阻碍,建议同步落地配套措施:
-
提供模板:在项目 README 或 commit-msg 钩子中预填格式,如
PROJ-XXX: feat: add login button -
支持多格式:正则可放宽为
([A-Z]{2,}-\d+)|\b[A-Z]{2,}-\d+\b,兼容括号包裹或行首独立出现 -
跳过例外场景:允许特定 message 前缀绕过,如
chore: release v1.2.0或docs: update readme,但需在钩子中显式声明白名单 - 对接 Jira API(可选):在 pre-receive 中调用 Jira REST 接口验证工单是否存在且处于开放状态,进一步防伪造
服务端钩子生效后,任何不含合规 Jira 号的推送都会被硬性拦截,无需依赖开发者自觉。


















