Git钩子脚本如何检查变更管理

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查变更管理

  1. 变更范围与文件类型检查
  2. 代码质量与规范检查
  3. 提交信息规范检查
  4. 变更日志检查
  5. 分支命名规范检查
  6. 综合示例:完整变更管理检查脚本
  7. 钩子脚本部署建议
  8. 最佳实践建议

Git 钩子脚本(特别是 pre-commitcommit-msg 钩子)非常适合用于自动化变更管理检查,以下是几种常见的检查策略及对应的钩子脚本实现示例。

变更范围与文件类型检查

禁止提交特定文件类型

#!/bin/bash
# .git/hooks/pre-commit
# 禁止提交 .log、.tmp 文件
for file in $(git diff --cached --name-only); do
    if [[ "$file" =~ \.(log|tmp|bak|swp)$ ]]; then
        echo "错误:禁止提交临时文件:$file"
        exit 1
    fi
done

检查文件大小限制

#!/bin/bash
# .git/hooks/pre-commit
MAX_SIZE=$((10 * 1024 * 1024))  # 10MB
git diff --cached --name-only -z | xargs -0 stat --format='%s %n' | while read size file; do
    if [ "$size" -gt "$MAX_SIZE" ]; then
        echo "错误:文件过大 (>10MB):$file"
        exit 1
    fi
done

代码质量与规范检查

ESLint 检查(JavaScript/TypeScript)

#!/bin/bash
# .git/hooks/pre-commit
# 获取暂存区中修改的 JS/TS 文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|tsx|jsx)$')
if [ -n "$STAGED_FILES" ]; then
    echo "运行 ESLint 检查..."
    npx eslint $STAGED_FILES
    if [ $? -ne 0 ]; then
        echo "ESLint 检查失败,请修正后重新提交"
        exit 1
    fi
fi

Python 代码规范检查

#!/bin/bash
# .git/hooks/pre-commit
STAGED_PY=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')
if [ -n "$STAGED_PY" ]; then
    echo "运行 Flake8 检查..."
    flake8 $STAGED_PY
    if [ $? -ne 0 ]; then
        echo "Python 代码规范检查失败"
        exit 1
    fi
fi

提交信息规范检查

提交信息格式验证

#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# 检查提交信息格式: [类型]: 描述
# 类型: feat|fix|docs|style|refactor|test|chore
if ! echo "$COMMIT_MSG" | grep -qE '^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}$'; then
    echo "错误:提交信息格式不正确"
    echo "正确格式: [类型]: 描述"
    echo "示例: feat: 添加用户登录功能"
    echo "类型: feat|fix|docs|style|refactor|test|chore"
    exit 1
fi

变更日志检查

检查变更文件是否更新了 CHANGELOG

#!/bin/bash
# .git/hooks/pre-commit
# 检查是否有除 CHANGELOG 外的文件被修改
STAGED_FILES=$(git diff --cached --name-only)
HAS_CHANGES=$(echo "$STAGED_FILES" | grep -v "CHANGELOG.md" | wc -l)
HAS_CHANGELOG=$(echo "$STAGED_FILES" | grep "CHANGELOG.md" | wc -l)
if [ "$HAS_CHANGES" -gt 0 ] && [ "$HAS_CHANGELOG" -eq 0 ]; then
    echo "警告:您修改了代码但未更新 CHANGELOG.md"
    echo "是否继续提交?(y/n)"
    read -r response
    if [ "$response" != "y" ]; then
        exit 1
    fi
fi

分支命名规范检查

#!/bin/bash
# .git/hooks/pre-commit
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
# 允许的分支命名模式
# feature/xxx, bugfix/xxx, hotfix/xxx, release/xxx
if [[ "$BRANCH_NAME" =~ ^(feature|bugfix|hotfix|release)/[a-z0-9_-]+$ ]]; then
    # 根据分支类型添加额外的检查
    case "$BRANCH_NAME" in
        feature/*)
            # 功能分支检查
            ;;
        bugfix/*)
            # 修复分支检查:确保有关联的 Issue 编号
            if [[ ! "$BRANCH_NAME" =~ -[0-9]+$ ]]; then
                echo "错误:bugfix 分支应包含 Issue 编号"
                echo "示例: bugfix/fix-login-123"
                exit 1
            fi
            ;;
    esac
else
    echo "警告:当前分支名称 '$BRANCH_NAME' 不符合命名规范"
    echo "推荐格式: feature/xxx, bugfix/xxx, hotfix/xxx"
fi

综合示例:完整变更管理检查脚本

#!/bin/bash
# .git/hooks/pre-commit
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
ERRORS=0
WARNINGS=0
echo "=== 变更管理检查开始 ==="
# 1. 获取所有变更文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
echo "变更文件数量: $(echo "$STAGED_FILES" | wc -l)"
# 2. 检查禁止提交的文件类型
echo -e "\n[检查1] 文件类型检查..."
for file in $STAGED_FILES; do
    if [[ "$file" =~ \.(log|tmp|bak|swp|DS_Store)$ ]]; then
        echo -e "${RED}错误:禁止提交临时文件:$file${NC}"
        ((ERRORS++))
    fi
done
# 3. 检查文件大小
echo -e "\n[检查2] 文件大小检查..."
MAX_SIZE=$((5 * 1024 * 1024))
while IFS= read -r file; do
    if [ -f "$file" ]; then
        size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
        if [ "$size" -gt "$MAX_SIZE" ]; then
            echo -e "${RED}错误:文件过大 (>5MB):$file (大小: $((size/1024/1024))MB)${NC}"
            ((ERRORS++))
        fi
    fi
done <<< "$STAGED_FILES"
# 4. 检查敏感信息
echo -e "\n[检查3] 敏感信息检查..."
for file in $STAGED_FILES; do
    if [ -f "$file" ] && [[ ! "$file" =~ \.(png|jpg|jpeg|gif|ico)$ ]]; then
        # 检查常见的敏感信息模式
        if grep -qP '(password|api_key|secret|token|credential|private_key)' "$file" 2>/dev/null; then
            echo -e "${YELLOW}警告:文件可能包含敏感信息:$file${NC}"
            ((WARNINGS++))
        fi
    fi
done
# 5. 检查是否有 TODO/FIXME 注释
echo -e "\n[检查4] TODO/FIXME 检查..."
for file in $STAGED_FILES; do
    if [ -f "$file" ] && [[ "$file" =~ \.(py|js|ts|java|go|rb|php)$ ]]; then
        if grep -qP '(TODO|FIXME|HACK|XXX)' "$file" 2>/dev/null; then
            echo -e "${YELLOW}警告:文件包含 TODO/FIXME 标记:$file${NC}"
            ((WARNINGS++))
        fi
    fi
done
# 6. 检查分支命名
echo -e "\n[检查5] 分支命名检查..."
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
if [[ "$BRANCH_NAME" == "main" || "$BRANCH_NAME" == "master" ]]; then
    echo -e "${RED}错误:禁止直接在主分支上提交${NC}"
    ((ERRORS++))
fi
# 汇总结果
echo -e "\n=== 检查完成 ==="
echo -e "${RED}错误: $ERRORS${NC}"
echo -e "${YELLOW}警告: $WARNINGS${NC}"
if [ $ERRORS -gt 0 ]; then
    echo -e "${RED}由于存在错误,提交被终止${NC}"
    exit 1
fi
echo -e "${GREEN}所有检查通过,允许提交${NC}"
exit 0

钩子脚本部署建议

  1. 赋予执行权限

    chmod +x .git/hooks/pre-commit
    chmod +x .git/hooks/commit-msg
  2. 团队共享配置:将钩子脚本放在项目仓库中

    mkdir -p .githooks
    cp .git/hooks/* .githooks/
  3. 全局配置:设置全局钩子路径

    git config --global core.hooksPath /path/to/global/hooks
  4. 使用 Husky(Node.js 项目):

    // package.json
    {
      "husky": {
        "hooks": {
          "pre-commit": "npm run test && npm run lint",
          "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
        }
      }
    }

最佳实践建议

  1. 渐进式执行:先以警告形式运行,待团队适应后再改为强制检查

  2. 提供跳过机制

    git commit --no-verify  # 跳过钩子检查
  3. 性能优化:避免在钩子中执行耗时操作(如完整测试套件)

  4. 错误信息清晰:提供明确的错误信息和修复建议

  5. 版本控制:将钩子脚本纳入版本管理,确保团队一致

通过合理配置 Git 钩子,可以有效实施变更管理策略,提高代码质量和团队协作效率。

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