Git钩子脚本如何检查改进计划

wen 实用脚本 1

我来详细介绍Git钩子脚本如何检查改进计划,这是一个很好的实践,可以在代码提交前自动验证和改进代码质量。

Git钩子脚本如何检查改进计划

基本检查框架

预提交钩子(pre-commit)

#!/bin/bash
# .git/hooks/pre-commit
echo "🔍 开始改进计划检查..."
# 收集变更文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
if [ -z "$STAGED_FILES" ]; then
    echo "✅ 没有需要检查的文件"
    exit 0
fi
# 初始化结果变量
ERRORS=0
WARNINGS=0

代码质量检查

语法和风格检查

# 语法检查函数
check_syntax() {
    local file=$1
    local ext="${file##*.}"
    case $ext in
        py)
            python -m py_compile "$file" 2>/dev/null || {
                echo "❌ Python语法错误: $file"
                return 1
            }
            ;;
        js|jsx)
            node -c "$file" 2>/dev/null || {
                echo "❌ JavaScript语法错误: $file"
                return 1
            }
            ;;
        ts|tsx)
            npx tsc --noEmit "$file" 2>/dev/null || {
                echo "❌ TypeScript语法错误: $file"
                return 1
            }
            ;;
        sh)
            bash -n "$file" 2>/dev/null || {
                echo "❌ Shell语法错误: $file"
                return 1
            }
            ;;
    esac
    return 0
}

代码复杂度检查

# 检查函数复杂度
check_complexity() {
    local file=$1
    local max_lines=100
    local max_nesting=3
    # 检查文件行数
    local lines=$(wc -l < "$file")
    if [ $lines -gt $max_lines ]; then
        echo "⚠️  文件过长 ($lines行): $file"
        WARNINGS=$((WARNINGS + 1))
    fi
    # 检查嵌套深度(示例:Python)
    if [[ "$file" == *.py ]]; then
        local max_depth=$(python3 -c "
import ast
with open('$file') as f:
    tree = ast.parse(f.read())
def get_depth(node, current=0):
    depths = [current]
    for child in ast.iter_child_nodes(node):
        if isinstance(child, (ast.If, ast.For, ast.While, ast.FunctionDef)):
            depths.extend(get_depth(child, current + 1))
    return depths
depths = get_depth(tree)
print(max(depths) if depths else 0)
" 2>/dev/null)
        if [ "$max_depth" -gt "$max_nesting" ]; then
            echo "⚠️  嵌套过深 (深度$max_depth): $file"
            WARNINGS=$((WARNINGS + 1))
        fi
    fi
}

安全检查

# 硬编码密码检查
check_secrets() {
    local file=$1
    # 检查常见的敏感信息模式
    patterns=(
        "password\s*=\s*['\"][^'\"]+['\"]"
        "api_key\s*=\s*['\"][^'\"]+['\"]"
        "secret\s*=\s*['\"][^'\"]+['\"]"
        "token\s*=\s*['\"][^'\"]+['\"]"
        "-----BEGIN (RSA|OPENSSH) PRIVATE KEY-----"
    )
    for pattern in "${patterns[@]}"; do
        if grep -qE "$pattern" "$file" 2>/dev/null; then
            echo "❌ 发现可能的敏感信息: $file"
            ERRORS=$((ERRORS + 1))
            return 1
        fi
    done
    return 0
}

测试覆盖检查

# 检查测试文件
check_test_coverage() {
    local file=$1
    local filename=$(basename "$file")
    local dir=$(dirname "$file")
    # 跳过测试文件本身
    if [[ "$filename" == test_* ]] || [[ "$filename" == *_test.* ]]; then
        return 0
    fi
    # 查找对应的测试文件
    local test_file="${dir}/test_${filename}"
    if [[ ! -f "$test_file" ]]; then
        test_file="${dir}/tests/test_${filename}"
    fi
    if [[ ! -f "$test_file" ]]; then
        echo "⚠️  缺少测试文件: $file"
        WARNINGS=$((WARNINGS + 1))
    fi
}

文档和注释检查

# 检查文档字符串
check_docs() {
    local file=$1
    if [[ "$file" == *.py ]]; then
        python3 -c "
import ast
with open('$file') as f:
    content = f.read()
    tree = ast.parse(content)
# 检查函数和类的文档
for node in ast.walk(tree):
    if isinstance(node, (ast.FunctionDef, ast.ClassDef)):
        if not ast.get_docstring(node):
            print(f'缺少文档: {node.name} at line {node.lineno}')
" 2>/dev/null | while read -r msg; do
            echo "⚠️  $msg (in $file)"
            WARNINGS=$((WARNINGS + 1))
        done
    fi
}

依赖检查

# 检查依赖更新
check_dependencies() {
    local file=$1
    # Python requirements.txt
    if [[ "$file" == "requirements.txt" ]]; then
        while IFS= read -r package; do
            if [[ "$package" == *">="* ]] || [[ "$package" == *"=="* ]]; then
                echo "⚠️  考虑使用精确版本: $package"
                WARNINGS=$((WARNINGS + 1))
            fi
        done < "$file"
    fi
    # Node.js package.json
    if [[ "$file" == "package.json" ]]; then
        if grep -q '"version": "\^' "$file" 2>/dev/null; then
            echo "⚠️  存在^版本依赖,建议锁定版本"
            WARNINGS=$((WARNINGS + 1))
        fi
    fi
}

主检查流程

# 主执行函数
main() {
    echo "=== 改进计划检查报告 ==="
    echo "检查时间: $(date)"
    echo "检查文件数: $(echo "$STAGED_FILES" | wc -l)"
    echo ""
    for file in $STAGED_FILES; do
        echo "--- 检查: $file ---"
        # 只检查代码文件
        case "$file" in
            *.py|*.js|*.ts|*.sh|*.go|*.java|*.rb|*.php)
                check_syntax "$file" || ERRORS=$((ERRORS + 1))
                check_complexity "$file"
                check_secrets "$file" || ERRORS=$((ERRORS + 1))
                check_test_coverage "$file"
                check_docs "$file"
                ;;
            requirements.txt|package.json|Gemfile)
                check_dependencies "$file"
                ;;
        esac
    done
    # 生成报告
    echo ""
    echo "=== 检查结果 ==="
    echo "❌ 错误: $ERRORS"
    echo "⚠️  警告: $WARNINGS"
    echo ""
    # 改进建议
    if [ $ERRORS -gt 0 ] || [ $WARNINGS -gt 0 ]; then
        echo "💡 改进建议:"
        [ $ERRORS -gt 0 ] && echo "- 请修复所有错误后再提交"
        [ $WARNINGS -gt 0 ] && echo "- 建议处理警告以提升代码质量"
        echo "- 考虑使用 'git commit --no-verify' 跳过检查(不推荐)"
    else
        echo "✅ 代码质量良好,可以提交!"
    fi
    # 根据错误数量决定是否阻止提交
    [ $ERRORS -gt 0 ] && exit 1
    exit 0
}
main

进阶功能

集成静态分析工具

# 集成多种检查工具
run_static_analysis() {
    local file=$1
    case "${file##*.}" in
        py)
            # Pylint
            pylint --rcfile=.pylintrc "$file" 2>/dev/null || true
            # Flake8
            flake8 --max-line-length=100 "$file" 2>/dev/null || true
            ;;
        js|ts)
            # ESLint
            npx eslint "$file" 2>/dev/null || true
            ;;
        go)
            # Golangci-lint
            golangci-lint run "$file" 2>/dev/null || true
            ;;
    esac
}

性能检查

# 检查性能问题
check_performance() {
    local file=$1
    if [[ "$file" == *.py ]]; then
        # 检查常见性能模式
        if grep -q "for.*in.*range(len" "$file" 2>/dev/null; then
            echo "⚠️  建议使用enumerate代替range(len()): $file"
        fi
        if grep -q "^import \*" "$file" 2>/dev/null; then
            echo "⚠️  避免使用通配符导入: $file"
        fi
    fi
    if [[ "$file" == *.js ]]; then
        if grep -q "== " "$file" 2>/dev/null; then
            echo "ℹ️  建议使用===代替==: $file"
        fi
    fi
}

安装和使用

  1. 安装钩子脚本
    #!/bin/bash
    # setup-hooks.sh

HOOKS_DIR=".git/hooks" mkdir -p "$HOOKS_DIR"

cat > "$HOOKS_DIR/pre-commit" << 'EOF'

这里是上面的完整pre-commit脚本内容

EOF

chmod +x "$HOOKS_DIR/pre-commit" echo "✅ Git钩子安装完成"


2. **跳过检查**(紧急情况):
```bash
git commit --no-verify -m "紧急修复"

这个检查系统可以根据项目需求进行定制,比如添加特定的业务规则检查、集成更多工具,或者根据团队规范调整警告级别,关键是要在保护代码质量和不影响开发效率之间找到平衡。

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