本文目录导读:

- 常见的日志策略检查项
- 示例脚本:检查 Conventional Commits 格式
- 更详细的脚本:检查多种规则
- 针对不同需求的其他检查示例
- 全局安装 hook(多个仓库共享)
- 使用 shell 脚本的注意事项
- 结合 CI 的额外建议
Git 钩子脚本通常通过 commit-msg 钩子来检查日志(提交信息)策略,这个钩子在用户输入提交信息之后、提交完成之前被触发。
以下是一个完整的检查日志策略的 commit-msg 钩子脚本示例,并说明了常见的检查项及部署方法。
常见的日志策略检查项
- 非空检查:提交信息不能为空。
- 格式检查:是否符合特定格式,
type(scope): subject(Conventional Commits)。 - 长度限制:第一行(标题)不能超过 50/72 个字符;正文每行不超过 72 个字符。
- 关键词屏蔽:禁止包含敏感词或临时标记(如
WIP、test、fixme)。 - 分支/issue 关联:提交信息是否包含 Issue 编号或 Jira 编号。
- 签名检查:是否包含
Signed-off-by或Co-authored-by行。
示例脚本:检查 Conventional Commits 格式
将以下脚本保存为 .git/hooks/commit-msg 并赋予可执行权限。
#!/bin/sh
#
# Git commit-msg hook: 检查提交信息是否符合 Conventional Commits 格式
# 规则:
# <type>[optional scope]: <description>
# [optional body]
# [optional footer(s)]
#
# 启用严格模式(可选)
# set -e
commit_msg_file="$1"
commit_msg=$(cat "$commit_msg_file")
# 定义正则匹配模式(Conventional Commits)
pattern="^(feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert)(\(.+\))?!?: .{1,}$"
# 检查是否匹配格式
if ! echo "$commit_msg" | grep -qE "$pattern"; then
echo "ERROR: 提交信息不符合 Conventional Commits 格式"
echo "格式: <type>(<scope>): <subject>"
echo "允许的 type: feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert"
echo "示例: feat(auth): 添加登录功能"
exit 1
fi
# 检查第一行长度(通常建议不超过 72)
first_line=$(echo "$commit_msg" | head -n1)
if [ ${#first_line} -gt 72 ]; then
echo "ERROR: 第一行(标题)长度 ${#first_line},不允许超过 72 个字符"
exit 1
fi
# 检查空提交信息
if [ -z "$commit_msg" ]; then
echo "ERROR: 提交信息不能为空"
exit 1
fi
# ✅ 所有检查通过
exit 0
更详细的脚本:检查多种规则
#!/bin/bash
commit_msg_file="$1"
commit_msg=$(cat "$commit_msg_file")
exit_code=0
echo "[commit-msg hook] 检查提交信息策略..."
# 1. 非空检查
if [ -z "$commit_msg" ]; then
echo "❌ 提交信息不能为空"
exit_code=1
fi
长度(超过50给出警告,超过72拒绝)
first_line=$(echo "$commit_msg" | head -n1)
if [ ${#first_line} -gt 72 ]; then
echo "❌ 标题超过 72 个字符 (当前: ${#first_line})"
exit_code=1
elif [ ${#first_line} -gt 50 ]; then
echo "⚠️ 标题超过 50 个字符 (建议不超过50)"
fi
# 3. 格式:必须包含冒号和空格
if ! echo "$first_line" | grep -qE ":\s"; then
echo "❌ 标题格式错误:必须包含 ': ' (冒号+空格)"
exit_code=1
fi
# 4. 不允许包含 WIP 或 FIXME
if echo "$commit_msg" | grep -qi "\bWIP\b"; then
echo "❌ 提交信息包含 'WIP',禁止提交"
exit_code=1
fi
# 5. 如果分支是 feature/xxx,要求提交信息包含 issue 编号
branch_name=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
if echo "$branch_name" | grep -qE "^feature/"; then
if ! echo "$commit_msg" | grep -qE "#[0-9]+"; then
echo "❌ 当前分支为 feature 分支,提交信息必须包含 Issue 编号(如 #123)"
exit_code=1
fi
fi
# 6. 检查是否包含 Signed-off-by (用于 DCO 认证)
# if ! echo "$commit_msg" | grep -q "Signed-off-by:"; then
# echo "❌ 缺少 Signed-off-by 行 (请使用 git commit -s)"
# exit_code=1
# fi
# 汇总结果
if [ $exit_code -ne 0 ]; then
echo ""
echo "🔴 提交信息策略检查未通过,请修改后重新提交。"
echo "提示: 可使用 'git commit --amend' 修改提交信息。"
fi
exit $exit_code
针对不同需求的其他检查示例
1 检查 Jira 编号(如项目 ID 开头)
# 要求提交信息必须包含 JIRA-XXX 的编号
if ! echo "$commit_msg" | grep -qE "[A-Z]+-[0-9]+"; then
echo "ERROR: 提交信息必须包含 Jira 编号 (如 PROJECT-123)"
exit 1
fi
2 禁止使用中文(部分团队要求纯英文)
if echo "$commit_msg" | grep -qP "[\x{4e00}-\x{9fa5}]"; then
echo "ERROR: 提交信息不能包含中文字符,请使用英文"
exit 1
fi
3 检查空行/分行(多行提交信息需要空行分隔标题和正文)
lines=$(echo "$commit_msg" | wc -l)
if [ "$lines" -gt 1 ]; then
# 如果有正文,必须在标题后留一个空行
second_line=$(echo "$commit_msg" | sed -n '2p')
if [ -n "$second_line" ]; then
echo "ERROR: 标题和正文之间必须有一个空行"
exit 1
fi
fi
全局安装 hook(多个仓库共享)
如果希望所有仓库都使用相同的提交信息检查逻辑,可以使用 全局 Git 钩子。
# 1. 创建全局钩子目录 git config --global core.hooksPath ~/.git-hooks # 2. 将脚本放入该目录 mkdir -p ~/.git-hooks cp commit-msg ~/.git-hooks/ chmod +x ~/.git-hooks/commit-msg
然后所有使用该 Git 版本的新仓库都会自动应用此钩子。
使用 shell 脚本的注意事项
- 可移植性:使用
#!/bin/sh而非#!/bin/bash能提高 macOS 等系统的兼容性(某些系统默认/bin/sh不是 bash)。 - 变量引用:尽量用双引号包裹变量(如
"$commit_msg"),防止特殊字符导致错误。 - 错误处理:所有检查失败时
exit 1,Git 会拒绝本次提交。 - 调试:可以临时添加
echo "DEBUG: $commit_msg" >&2输出到 stderr 以便调试。
结合 CI 的额外建议
Hook 仅作用于开发者本地环境,为了保险起见,建议在 CI(如 Jenkins、GitHub Actions)中也加入相似的提交信息校验:
# GitHub Actions 示例:check commit message
- name: Check commit message format
run: |
commit_msg=$(git log --format=%B -n1 ${{ github.sha }})
echo "Commit message: $commit_msg"
echo "$commit_msg" | grep -qE "^(feat|fix|docs): .+$" || exit 1
| 钩子名 | 触发时机 | 常用检查项 |
|---|---|---|
commit-msg |
提交信息输入后 | 格式、长度、非空、关键词 |
prepare-commit-msg |
提交信息编辑前 | 自动插入模板、分支名、issue号 |
最常用且推荐的做法是使用 commit-msg 钩子 编写 Shell 脚本,配合正则表达式检查提交信息的格式和内容策略。