本文目录导读:

Git 钩子脚本可以通过在 Git 操作的关键节点(如提交、推送、合并)执行自定义检查,来实现发布管理(Release Management)的自动化质量控制,以下是几种核心的检查策略和脚本实现思路。
核心检查目标通常包括:
- 版本号一致性:确保代码版本号(如
package.json、VERSION文件)与 Git Tag 或分支名匹配。 - 变更日志检查:确保本次发布有对应的
CHANGELOG.md记录。 - 代码质量与安全:运行测试、代码风格检查、依赖安全审计。
- 分支策略合规:确保只能从特定的分支(如
develop)合并到发布分支(如release或main)。
环境准备:项目配置文件
为了让脚本更灵活,建议在项目根目录创建一个 .releaserc 或类似配置文件(release-config.json),定义版本号文件、路径等。
示例 release-config.json:
{
"versionFile": "package.json",
"changelogFile": "CHANGELOG.md",
"releaseBranchPattern": "release/*",
"mainBranch": "main",
"developBranch": "develop"
}
核心钩子场景与脚本示例
Pre-commit 钩子 — 检查版本号文件是否未提交修改
适用时机:在创建发布分支后,对版本号文件进行修改并提交时。
脚本 .git/hooks/pre-commit (需要 chmod +x):
#!/bin/bash
# 检查本次提交是否修改了版本号文件,如果修改了,需确保有对应的 CHANGELOG 更新
# 读取配置 (简化示例,未读取JSON)
VERSION_FILE="package.json"
CHANGELOG_FILE="CHANGELOG.md"
# 检查暂存区是否包含版本号文件
if git diff --cached --name-only | grep -q "$VERSION_FILE"; then
# 检查暂存区是否也包含了 CHANGELOG 文件
if ! git diff --cached --name-only | grep -q "$CHANGELOG_FILE"; then
echo "❌ 错误: 你修改了 $VERSION_FILE,请同时更新 $CHANGELOG_FILE 并提交。"
exit 1
fi
fi
exit 0
Pre-push 钩子 — 检查分支合规性与版本号验证
适用时机:开发者将发布分支推送到远程时,这是发布管理中最常用且最重要的钩子。
脚本 .git/hooks/pre-push:
#!/bin/bash
# 参数: 远程名称 远程URL
remote="$1"
url="$2"
# 读取标准输入获取本地/远程引用信息
while read local_ref local_sha remote_ref remote_sha
do
# 只检查推送的引用是否为分支,且不是删除操作
if [[ "$local_ref" =~ ^refs/heads/ && "$remote_sha" != "0000000000000000000000000000000000000000" ]]; then
branch_name="${local_ref#refs/heads/}"
# 1. 检查是否向 main 或 release 分支推送
if [[ "$branch_name" == "main" || "$branch_name" == "release"* ]]; then
echo "🔒 禁止直接推送至 $branch_name 分支"
echo " 请通过 Pull Request 合并到该分支"
exit 1
fi
# 2. 如果是 release/* 分支推送,检查版本号和 Tag
if [[ "$branch_name" == release/* ]]; then
echo "🚀 检测到发布分支推送: $branch_name"
# 提取版本号 (假设分支名格式为 release/v1.2.3)
version_from_branch=$(echo "$branch_name" | cut -d'/' -f2)
# 读取 package.json 中的版本号 (使用 node 或 awk)
version_from_file=$(node -p "require('./package.json').version")
if [[ "$version_from_branch" != "v$version_from_file" && "$version_from_branch" != "$version_from_file" ]]; then
echo "❌ 错误: 分支名版本 ($version_from_branch) 与 package.json 版本 ($version_from_file) 不匹配"
exit 1
fi
# 选择: 检查 CHANGELOG
if ! grep -q "$version_from_branch" CHANGELOG.md; then
echo "❌ 错误: CHANGELOG.md 中未找到版本 $version_from_branch 的更新记录"
exit 1
fi
echo "✅ 发布分支检查通过"
fi
fi
done
exit 0
Post-commit 钩子 — 版本号自动校验与 Tag 前置检查
适用时机:在提交完成后,检查是否满足打 Tag 的条件。
脚本 .git/hooks/post-commit (辅助角色):
#!/bin/bash
# 获取当前分支名
branch=$(git rev-parse --abbrev-ref HEAD)
# 只在 release 分支上执行
if [[ "$branch" == release/* ]]; then
version=$(node -p "require('./package.json').version")
echo "🔔 提示: 当前分支 '$branch' (版本 $version)"
echo " 如果你打算为本次发布打 Tag,请确保:"
echo " 1. 所有测试已通过 (运行 npm test)"
echo " 2. CHANGELOG.md 已更新完整"
fi
exit 0
高级发布管理钩子组合
为了确保发布流程的严谨性,推荐使用 Prepare-commit-msg 或 Commit-msg 钩子来标准化提交信息,以便自动化生成变更日志。
Commit-msg 钩子 — 强制提交信息包含 Issue 或 Change 类型
脚本 .git/hooks/commit-msg:
#!/bin/bash
commit_message_file="$1"
commit_message=$(cat "$commit_message_file")
# 检查提交信息格式 ( "fix: #123 修复登录bug")
# 用于 release 分支的提交,必须包含类型前缀
if ! echo "$commit_message" | grep -qE "^(feat|fix|chore|docs|refactor|test):"; then
echo "❌ 提交信息格式错误,必须包含类型前缀: feat, fix, chore, docs, refactor, test"
echo " 示例: fix: #123 修复登录页面崩溃"
exit 1
fi
exit 0
推荐的完整发布流程钩子配置
| 执行阶段 | 钩子名 | 主要职责 | 失败时后果 |
|---|---|---|---|
| 提交前 | pre-commit |
运行单元测试、代码格式化检查 | 不允许提交 |
| 提交时 | commit-msg |
检查提交信息格式(类型+描述) | 不允许提交 |
| 推送前 | pre-push |
检查分支合规、版本号一致性、CHANGELOG | 推送中断 |
| 合并后 | post-merge (可选) |
自动打 Tag、触发 CI/CD | 仅提示 |
注意事项与最佳实践
- 钩子共享性差:
.git/hooks目录默认不提交到 Git 仓库,团队需要手动配置或使用工具(如husky、pre-commit)来统一管理。 - 脚本健壮性:
- 使用
#!/bin/bash而不是#!/bin/sh,因为bash支持更多条件判断和数组特性。 - 使用
set -e让脚本在遇到错误时立即退出。 - 对所有外部输入(如分支名)进行转义或正则匹配。
- 使用
- 跳过钩子:提供紧急跳过机制,但严格限制。
- 使用
git commit -n跳过pre-commit钩子。 - 使用
git push --no-verify跳过pre-push钩子。 - 最佳实践:记录跳过行为,例如在 CI/CD 环境变量中设置
SKIP_RELEASE_CHECK=1作为替代方案。
- 使用
- 使用工具简化管理:
- Husky (Node.js项目):
npx husky add .husky/pre-push "bash scripts/check-release.sh" - pre-commit (Python/多语言):通过
.pre-commit-config.yaml配置。
- Husky (Node.js项目):
- 与 CI/CD 协同:Git 钩子负责本地快速检查(难以绕过),但最终的质量门禁(如 Tag 签名、二进制构建)应在 GitHub Actions / GitLab CI 中执行。
最终示例:结合 Husky 的发布检查脚本
使用 Husky 简化后,你的 ./husky/pre-push 文件内容如下(假设脚本在 scripts/ 目录):
#!/bin/sh . "$(dirname "$0")/_/husky.sh" # 运行发布检查脚本 bash scripts/check-release.sh
而 scripts/check-release.sh 则包含上述 pre-push 的完整逻辑。
通过以上配置,Git 钩子脚本能够有效拦截不规范的操作,确保发布版本的版本号、变更日志和分支策略严格一致,从而提升代码发布的稳定性和可追溯性。