Git钩子脚本如何检查流程制度

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查流程制度

  1. 代码规范与风格检查(如 ESLint、Prettier)
  2. commit message 格式检查(如 Conventional Commits)
  3. 禁止敏感信息泄露
  4. 分支命名规范检查
  5. 强制运行测试(单元测试/集成测试)
  6. 文件大小/类型限制(防止大文件或非必要文件)
  7. 组合多个检查(综合脚本)
  8. ⚠️ 部署与管理建议

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 等被提交。

制度要求:禁止提交包含 passwordapi_keysecret 等关键词的文件或真实值。

脚本示例

#!/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-pushpre-commit 中运行测试,确保不会破坏已有功能。

制度要求:推送前必须通过当前模块的所有单元测试。

脚本示例

#!/bin/sh
echo "🧪 运行单元测试..."
npm test -- --watchAll=false --bail
if [ $? -ne 0 ]; then
  echo "❌ 测试未通过,请修复后再次提交。"
  exit 1
fi
exit 0

文件大小/类型限制(防止大文件或非必要文件)

pre-commit 中检查暂存区文件的大小和类型。

制度要求:禁止提交超过 5MB 的文件,禁止提交 .DS_Store*.lognode_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

⚠️ 部署与管理建议

  1. 使用 core.hooksPath 集中管理: 将钩子脚本放在项目根目录的 .githooks/ 文件夹中,然后执行:

    git config core.hooksPath .githooks

    这样钩子脚本会跟随仓库,每次 git clone 后只需执行一次该命令即可生效。

  2. 使用工具库简化开发

    • husky:最流行的 Git 钩子管理工具(针对 npm 项目)。
    • pre-commit:Python 生态的钩子管理框架,支持各种语言。
    • gitleaks / truffleHog:专业的敏感信息检测工具(比 grep 更强大)。
  3. 赋予执行权限: 脚本必须具有可执行权限:

    chmod +x .githooks/pre-commit
    chmod +x .githooks/commit-msg
  4. 处理跳过需求(紧急情况): 允许用户通过 --no-verify 跳过钩子(如 git commit --no-verify)。制度上应限制这种行为,例如通过 CI/CD 流水线再次强制执行相同检查,让跳过钩子只能在本地临时使用,无法绕过远程服务器的检查。

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