本文目录导读:

- 代码规范与风格检查(如 ESLint、Prettier)
- commit message 格式检查(如 Conventional Commits)
- 禁止敏感信息泄露
- 分支命名规范检查
- 强制运行测试(单元测试/集成测试)
- 文件大小/类型限制(防止大文件或非必要文件)
- 组合多个检查(综合脚本)
- ⚠️ 部署与管理建议
Git 钩子脚本是流程制度落地的第一道防线,它可以在代码提交(commit)或推送(push)等关键节点自动执行检查,防止不规范的操作进入仓库。
以下是基于不同流程制度的检查方法与脚本示例,按常见的检查场景分类:
代码规范与风格检查(如 ESLint、Prettier)
这是最常用的场景,通常在 pre-commit 钩子中执行。
制度要求:提交前代码必须通过 lint 检查,否则禁止提交。
脚本示例(.git/hooks/pre-commit):
#!/bin/sh
# 获取暂存区(即将提交)的 js/ts 文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|jsx|ts|tsx|vue)$')
if [ -n "$STAGED_FILES" ]; then
echo "🔍 运行 ESLint 检查..."
# 只检查暂存区的文件,而非全部文件
npx eslint $STAGED_FILES
if [ $? -ne 0 ]; then
echo "❌ 代码规范检查失败,请修复后再提交。"
exit 1
fi
fi
exit 0
commit message 格式检查(如 Conventional Commits)
在 commit-msg 钩子中检查提交信息是否符合 Angular、Conventional Commits 等规范。
制度要求:提交信息必须符合 type(scope): subject 格式,如 feat(login): add login page。
脚本示例(.git/hooks/commit-msg):
#!/bin/sh
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# 正则匹配:type(scope): description
# 支持 feat/fix/docs/style/refactor/perf/test/chore 等
REGEX="^(feat|fix|docs|style|refactor|perf|test|chore|ci)(\([a-zA-Z0-9._-]+\))?: .{1,100}$"
if ! echo "$COMMIT_MSG" | grep -qE "$REGEX"; then
echo "❌ 提交信息格式不符合规范!"
echo "格式要求:type(scope): description"
echo "示例:feat(user-api): 添加用户登录接口"
exit 1
fi
exit 0
禁止敏感信息泄露
在 pre-commit 钩子中扫描暂存区,防止密码、密钥、token 等被提交。
制度要求:禁止提交包含 password、api_key、secret 等关键词的文件或真实值。
脚本示例:
#!/bin/sh
SUSPICIOUS_KEYWORDS="password|api_key|secret|token|private_key"
echo "🔐 扫描敏感信息..."
STAGED_FILES=$(git diff --cached --name-only)
for FILE in $STAGED_FILES; do
# 跳过二进制文件
if [[ "$FILE" == *".jpg" ]] || [[ "$FILE" == *".png" ]]; then
continue
fi
# 检查文件内容是否包含敏感关键词
if git show :"$FILE" | grep -qiE "$SUSPICIOUS_KEYWORDS"; then
echo "❌ 文件 $FILE 包含敏感信息(关键词匹配到 password/secret 等)"
exit 1
fi
done
exit 0
分支命名规范检查
在 pre-push 钩子中检查当前分支名是否符合命名规范。
制度要求:分支必须遵循 feature/、bugfix/、hotfix/、release/ 等前缀。
脚本示例(.git/hooks/pre-push):
#!/bin/sh BRANCH_NAME=$(git symbolic-ref --short HEAD) # 允许的分支模式(可根据团队制度调整) # feature/xxx, bugfix/xxx, hotfix/xxx, release/x.x.x, main, develop REGEX="^(feature|bugfix|hotfix|release)/[a-zA-Z0-9._-]+|main|develop|master$" if ! echo "$BRANCH_NAME" | grep -qE "$REGEX"; then echo "❌ 分支名称 '$BRANCH_NAME' 不符合规范!" echo "允许的格式:feature/xxx, bugfix/xxx, hotfix/xxx, release/x.x, main, develop" exit 1 fi exit 0
强制运行测试(单元测试/集成测试)
在 pre-push 或 pre-commit 中运行测试,确保不会破坏已有功能。
制度要求:推送前必须通过当前模块的所有单元测试。
脚本示例:
#!/bin/sh echo "🧪 运行单元测试..." npm test -- --watchAll=false --bail if [ $? -ne 0 ]; then echo "❌ 测试未通过,请修复后再次提交。" exit 1 fi exit 0
文件大小/类型限制(防止大文件或非必要文件)
在 pre-commit 中检查暂存区文件的大小和类型。
制度要求:禁止提交超过 5MB 的文件,禁止提交 .DS_Store、*.log、node_modules(虽然已在 .gitignore 中,但可以作为双重保险)。
脚本示例:
#!/bin/sh
MAX_SIZE=$((5 * 1024 * 1024)) # 5MB
echo "📦 检查文件大小和类型..."
git diff --cached --name-only --diff-filter=ACM | while read -r file; do
# 检查文件是否存在(删除的文件不检查)
if [ -f "$file" ]; then
SIZE=$(stat -f%z "$file" 2>/dev/null || stat --printf="%s" "$file" 2>/dev/null)
if [ "$SIZE" -gt "$MAX_SIZE" ]; then
echo "❌ 文件 $file 超过 5MB(大小: $SIZE bytes),拒绝提交。"
exit 1
fi
fi
done
# 检查禁止的文件名
PROHIBITED_PATTERNS="\.DS_Store|\.log$|Thumbs\.db"
git diff --cached --name-only --diff-filter=ACM | while read -r file; do
if echo "$file" | grep -qiE "$PROHIBITED_PATTERNS"; then
echo "❌ 禁止提交系统文件:$file"
exit 1
fi
done
exit 0
组合多个检查(综合脚本)
实际项目中通常需要组合上述多个检查,以下是 pre-commit 的完整示例:
#!/bin/bash
# 如果任何命令失败,立即退出
set -e
echo "=== 开始预提交检查 ==="
# 1. 检查 lint(仅暂存区文件)
echo "1️⃣ 检查代码规范(ESLint)..."
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts)$' || true)
if [ -n "$STAGED_FILES" ]; then
npx eslint $STAGED_FILES
fi
# 2. 检查单元测试(只运行受影响模块的测试)
echo "2️⃣ 运行单元测试..."
npm test -- --findRelatedTests $STAGED_FILES --bail 2>/dev/null || npm test -- --bail
# 3. 检查敏感信息
echo "3️⃣ 检查敏感信息..."
if git diff --cached -U0 | grep -qiE 'password|secret|api_key'; then
echo "❌ 检测到敏感信息,拒绝提交。"
exit 1
fi
# 4. 检查文件大小
echo "4️⃣ 检查文件大小..."
git diff --cached --name-only --diff-filter=ACM | while read file; do
if [ -f "$file" ]; then
size=$(du -k "$file" | cut -f1)
if [ "$size" -gt 5120 ]; then # 5MB
echo "❌ 文件 $file 超过 5MB,拒绝提交。"
exit 1
fi
fi
done
echo "✅ 全部检查通过!"
exit 0
⚠️ 部署与管理建议
-
使用
core.hooksPath集中管理: 将钩子脚本放在项目根目录的.githooks/文件夹中,然后执行:git config core.hooksPath .githooks
这样钩子脚本会跟随仓库,每次
git clone后只需执行一次该命令即可生效。 -
使用工具库简化开发:
- husky:最流行的 Git 钩子管理工具(针对 npm 项目)。
- pre-commit:Python 生态的钩子管理框架,支持各种语言。
- gitleaks / truffleHog:专业的敏感信息检测工具(比 grep 更强大)。
-
赋予执行权限: 脚本必须具有可执行权限:
chmod +x .githooks/pre-commit chmod +x .githooks/commit-msg
-
处理跳过需求(紧急情况): 允许用户通过
--no-verify跳过钩子(如git commit --no-verify)。制度上应限制这种行为,例如通过 CI/CD 流水线再次强制执行相同检查,让跳过钩子只能在本地临时使用,无法绕过远程服务器的检查。