Git钩子脚本如何检查日志策略

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查日志策略

  1. 常见的日志策略检查项
  2. 示例脚本:检查 Conventional Commits 格式
  3. 更详细的脚本:检查多种规则
  4. 针对不同需求的其他检查示例
  5. 全局安装 hook(多个仓库共享)
  6. 使用 shell 脚本的注意事项
  7. 结合 CI 的额外建议

Git 钩子脚本通常通过 commit-msg 钩子来检查日志(提交信息)策略,这个钩子在用户输入提交信息之后、提交完成之前被触发。

以下是一个完整的检查日志策略的 commit-msg 钩子脚本示例,并说明了常见的检查项及部署方法。

常见的日志策略检查项

  • 非空检查:提交信息不能为空。
  • 格式检查:是否符合特定格式,type(scope): subject (Conventional Commits)。
  • 长度限制:第一行(标题)不能超过 50/72 个字符;正文每行不超过 72 个字符。
  • 关键词屏蔽:禁止包含敏感词或临时标记(如 WIPtestfixme)。
  • 分支/issue 关联:提交信息是否包含 Issue 编号或 Jira 编号。
  • 签名检查:是否包含 Signed-off-byCo-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 脚本,配合正则表达式检查提交信息的格式和内容策略。

抱歉,评论功能暂时关闭!