本文目录导读:

Git钩子脚本检查注释质量主要通过 commit-msg 钩子实现,以下是几种常见的检查方式和完整示例:
基本检查脚本 (commit-msg 钩子)
安装位置
.git/hooks/commit-msg
基础示例:检查提交信息格式
#!/bin/sh
# commit-msg 钩子
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3
# 读取提交信息
commit_message=$(cat "$COMMIT_MSG_FILE")
# 1. 检查信息是否为空
if [ -z "$commit_message" ]; then
echo "错误:提交信息不能为空!" >&2
exit 1
fi
# 2. 检查信息长度(第一行不超过72字符)
first_line=$(echo "$commit_message" | head -n1)
if [ ${#first_line} -gt 72 ]; then
echo "错误:提交信息第一行不能超过72个字符!" >&2
exit 1
fi
# 3. 检查是否以大写字母开头
if ! echo "$first_line" | grep -q "^[A-Z]"; then
echo "错误:提交信息应该以大写字母开头!" >&2
exit 1
fi
# 4. 检查是否包含有效的提交类型
if ! echo "$first_line" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)"; then
echo "错误:提交信息应该包含有效的类型前缀!" >&2
echo "可用类型: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert" >&2
exit 1
fi
exit 0
高级检查:严格格式规范
#!/bin/sh
# commit-msg 钩子 - 严格格式检查
COMMIT_MSG_FILE=$1
commit_message=$(cat "$COMMIT_MSG_FILE")
subject_line=$(echo "$commit_message" | head -n1)
body_lines=$(echo "$commit_message" | tail -n +3)
# 定义错误函数
error_exit() {
echo "错误:$1" >&2
exit 1
}
# 1. 检查提交信息长度
[ -z "$commit_message" ] && error_exit "提交信息不能为空"
# 2. 检查主题行格式 (类型(作用域): 描述)
if ! echo "$subject_line" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)\(.+\): .+"; then
echo "提交信息格式不正确!" >&2
echo "正确的格式: <type>(<scope>): <subject>" >&2
echo "类型: feat, fix, docs, style, refactor, test, chore, perf" >&2
error_exit "请修改提交信息"
fi
# 3. 检查主题行长度
[ ${#subject_line} -gt 72 ] && error_exit "主题行不能超过72个字符"
# 4. 检查主题行是否以句号结尾
echo "$subject_line" | grep -q "\.$" && error_exit "主题行不应该以句号结尾"
# 5. 检查是否有空行分隔主题和正文
if [ -n "$body_lines" ]; then
second_line=$(echo "$commit_message" | sed -n '2p')
[ -n "$second_line" ] && error_exit "主题行和正文之间需要空行"
# 6. 检查正文行长度
echo "$body_lines" | while IFS= read -r line; do
[ ${#line} -gt 72 ] && error_exit "正文行不能超过72个字符"
done
fi
exit 0
使用正则表达式验证
#!/bin/sh
# commit-msg 钩子 - 正则验证
COMMIT_MSG_FILE=$1
commit_message=$(cat "$COMMIT_MSG_FILE")
# 定义严格格式的正则
PATTERN="^(feat|fix|hotfix|docs|style|refactor|perf|test|chore|revert|ci)(\(.+\))?: .{1,50}"
# Issue 编号格式 (可选)
ISSUE_PATTERN="(#[0-9]+|JIRA-[0-9]+)"
# 功能分支完成的验证
COMPLETE_PATTERN="^(feat|fix)\(.+\): (add|update|fix|remove|change) .+"
validate_commit_message() {
local msg="$1"
# 检查基本格式
if [[ ! "$msg" =~ $PATTERN ]]; then
echo "提交信息格式错误" >&2
echo "正确格式: type(scope): subject" >&2
return 1
fi
# 可选:检查是否包含 issue 引用
# if [[ ! "$msg" =~ $ISSUE_PATTERN ]]; then
# echo "警告:提交信息应该包含 Issue 编号" >&2
# fi
return 0
}
validate_commit_message "$commit_message"
集成多种检查的组合脚本
#!/bin/sh
# commit-msg 钩子 - 综合检查
COMMIT_MSG_FILE=$1
commit_message=$(cat "$COMMIT_MSG_FILE")
errors=0
# 检查函数
check_not_empty() {
[ -z "$commit_message" ] && echo "提交信息不能为空" && return 1
return 0
}
check_subject_length() {
first_line=$(echo "$commit_message" | head -n1)
[ ${#first_line} -gt 72 ] && echo "主题行超过72字符" && return 1
return 0
}
check_type_format() {
first_line=$(echo "$commit_message" | head -n1)
case "$first_line" in
feat:*|fix:*|docs:*|style:*|refactor:*|test:*|chore:*|perf:*|ci:*|build:*|revert:*)
return 0 ;;
*)
echo "无效的提交类型"
echo "可用类型: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert"
return 1 ;;
esac
}
check_blank_line() {
local line_count=$(echo "$commit_message" | wc -l)
if [ "$line_count" -gt 1 ]; then
second_line=$(echo "$commit_message" | sed -n '2p')
[ -n "$second_line" ] && echo "主题和正文之间需要空行" && return 1
fi
return 0
}
check_body_wrapping() {
local body=$(echo "$commit_message" | tail -n +3)
[ -z "$body" ] && return 0
echo "$body" | while IFS= read -r line; do
if [ ${#line} -gt 72 ]; then
echo "正文行超过72字符: $line"
return 1
fi
done
}
# 执行所有检查
check_not_empty || errors=$((errors + 1))
check_subject_length || errors=$((errors + 1))
check_type_format || errors=$((errors + 1))
check_blank_line || errors=$((errors + 1))
check_body_wrapping || errors=$((errors + 1))
# 输出检查结果
if [ $errors -gt 0 ]; then
echo "发现 $errors 个错误,请修正后重新提交" >&2
exit 1
fi
exit 0
使用第三方工具
使用 commitlint(推荐)
# 安装 npm install -g @commitlint/cli @commitlint/config-conventional # commit-msg 钩子 #!/bin/sh ./node_modules/.bin/commitlint --edit $1
配置文件 commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor',
'test', 'chore', 'perf', 'ci', 'build', 'revert'
]],
'scope-case': [2, 'always', 'lower-case'],
'subject-case': [2, 'always', 'sentence-case'],
'subject-empty': [2, 'never'],
'subject-max-length': [2, 'always', 72],
'body-leading-blank': [2, 'always'],
'body-max-line-length': [1, 'always', 72]
}
};
最佳实践
推荐的提交信息格式
type(scope): subject
body
footer
类型说明
- feat: 新功能
- fix: 修复bug
- docs: 文档更新
- style: 代码格式(不影响功能)
- refactor: 重构
- test: 测试相关
- chore: 构建过程或辅助工具变动
- perf: 性能优化
安装和测试钩子
# 赋予执行权限 chmod +x .git/hooks/commit-msg # 测试钩子 echo "test message" | .git/hooks/commit-msg /dev/stdin # 或者创建临时提交测试 git commit --allow-empty -m "test: test commit"
通过使用这些钩子脚本,可以确保团队遵循一致的提交信息规范,提高代码管理的可维护性和可读性。