本文目录导读:

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"
通过使用这些钩子脚本,可以确保团队遵循一致的提交信息规范,提高代码管理的可维护性和可读性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播