Git钩子脚本如何检查演练计划

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查演练计划

  1. 核心思路
  2. 场景一:检查演练计划文件是否存在
  3. 场景二:检查演练计划文件内容格式(如状态、日期)
  4. 场景三:检查演练计划是否被意外修改(加锁机制)
  5. 场景四:检查演练计划文件中的日期是否合理
  6. 场景五:结合外部脚本或命令进行复杂验证
  7. 如何部署这些脚本
  8. 常见问题与技巧
  9. 推荐的工具:pre-commit 框架

Git 钩子脚本可以通过检查特定文件内容、文件是否存在、分支命名规范或调用自定义逻辑等方式,来验证“演练计划”是否满足要求。

由于“演练计划”在 Git 仓库中体现为具体的文件(如 .md.json.yaml 或特定目录下的文件),以下是几种常见的检查实现方式。

核心思路

pre-commit(提交前)或 pre-push(推送前)钩子中,使用 git diffgit ls-treegrep 等命令,对演练计划相关文件进行内容或结构校验。


检查演练计划文件是否存在

需求:每次提交必须包含一个名为 drill-plan.md 的文件,否则禁止提交。

脚本示例(.git/hooks/pre-commit

#!/bin/sh
# 获取本次提交即将变更的文件列表(暂存区)
staged_files=$(git diff --cached --name-only)
# 检查是否包含演练计划文件
if echo "$staged_files" | grep -q "drill-plan.md"; then
    exit 0
else
    echo "错误:本次提交未包含 drill-plan.md 文件!"
    echo "请确保演练计划已暂存。"
    exit 1
fi

改进版本(支持特定目录)

#!/bin/sh
required_dir="plans/drill/"
staged_files=$(git diff --cached --name-only)
has_plan=false
for file in $staged_files; do
    if echo "$file" | grep -q "^${required_dir}"; then
        has_plan=true
        break
    fi
done
if [ "$has_plan" = false ]; then
    echo "错误:暂存区中不存在 ${required_dir} 目录下的演练计划文件。"
    exit 1
fi

检查演练计划文件内容格式(如状态、日期)

需求:演练计划文件(如 drill-plan.yaml)必须包含 status: approved 字段。

脚本示例(.git/hooks/pre-commit

#!/bin/sh
staged_files=$(git diff --cached --name-only)
for file in $staged_files; do
    # 仅检查以 .yaml 结尾的文件
    case "$file" in
        *drill-plan*.yaml|*drill-plan*.yml)
            # 从暂存区获取文件内容(而非工作目录)
            content=$(git show :"$file")
            # 检查是否包含 approved 状态
            if ! echo "$content" | grep -q "status: approved"; then
                echo "错误:文件 $file 中的状态不是 'approved'。"
                exit 1
            fi
            ;;
    esac
done

注意事项

  • git show :"$file" 获取暂存区中的文件内容,这是关键——如果用户修改了工作目录但未暂存,这里检查的是暂存区的内容。
  • 使用 case 通配符匹配文件名,避免硬编码路径。

检查演练计划是否被意外修改(加锁机制)

需求:如果演练计划已被标记为“最终版”,则禁止任何人修改(除非特定用户或分支)。

脚本示例(.git/hooks/pre-commit

#!/bin/sh
# 定义只读文件或目录
protected_files=("plans/final_drill_plan.md")
for file in "${protected_files[@]}"; do
    if git diff --cached --name-only | grep -q "$file"; then
        echo "错误:$file 是受保护的演练计划文件,禁止修改!"
        echo "如需修改,请联系管理员。"
        exit 1
    fi
done

检查演练计划文件中的日期是否合理

需求:演练计划中的日期 date: 不能早于当前时间(不能使用过去的日期)。

脚本示例(.git/hooks/pre-commit

#!/bin/sh
staged_files=$(git diff --cached --name-only)
for file in $staged_files; do
    case "$file" in
        *drill_plan*
            # 提取暂存区文件中的日期行
            plan_date=$(git show :"$file" | grep -E "^date:" | awk '{print $2}')
            if [ -z "$plan_date" ]; then
                echo "警告:文件 $file 中未找到 date 字段,跳过日期检查。"
                continue
            fi
            current_date=$(date +%Y-%m-%d)
            # 比较日期(假设格式为 YYYY-MM-DD)
            if [ "$plan_date" \< "$current_date" ]; then
                echo "错误:$file 中的日期 $plan_date 早于当前日期 $current_date。"
                exit 1
            fi
            ;;
    esac
done

结合外部脚本或命令进行复杂验证

需求:使用独立的验证脚本(如 validate_plan.py)对演练计划进行结构化检查(JSON Schema、完整性等)。

脚本示例(.git/hooks/pre-commit

#!/bin/sh
# 获取本次变更的演练计划文件列表
plan_files=$(git diff --cached --name-only | grep -E "plans/drill/.*\.(json|yaml|yml)$")
if [ -z "$plan_files" ]; then
    exit 0  # 没有演练计划文件变更,直接通过
fi
# 针对每个文件执行外部验证脚本
for file in $plan_files; do
    # 将暂存区文件内容传递给验证脚本
    git show :"$file" | validate_plan.py "$file"
    if [ $? -ne 0 ]; then
        echo "错误:演练计划验证失败:$file"
        exit 1
    fi
done

如何部署这些脚本

  1. 创建钩子文件

    # 进入你的 Git 仓库
    cd /path/to/your/repo
    cat > .git/hooks/pre-commit << 'EOF'
    # 将上述脚本内容粘贴到这里
    EOF
    chmod +x .git/hooks/pre-commit
  2. 将钩子纳入版本管理(可选)

    • 创建一个 scripts/git-hooks/ 目录,存放钩子脚本。
    • 通过 git config core.hooksPath scripts/git-hooks 让团队共享钩子。
    • 或者使用 pre-commit 框架管理(推荐)。
  3. 测试脚本

    # 故意不包含演练计划进行提交尝试
    echo "test" > other.txt
    git add other.txt
    git commit -m "test"
    # 应该被拒绝

常见问题与技巧

  • 跨越暂存区:确保检查的是 git diff --cached(暂存区内容),而不是工作目录的 git diff,钩子运行时,用户已经执行了 git add,但尚未提交。
  • 处理跨平台路径:在 Windows 环境中使用 git bash 或确保脚本兼容 sh(不要依赖 bash 特有语法)。
  • 性能考虑:如果演练计划文件很多,避免在钩子中加载整个文件内容(使用 git show 按需读取)。
  • 跳过钩子:用户可以通过 git commit --no-verify 跳过钩子,因此钩子不应作为唯一的权限控制手段,更多是辅助提醒。

推荐的工具:pre-commit 框架

如果你需要更复杂的、可共享的钩子管理,建议使用 pre-commit 框架,你可以编写一个自定义钩子(如 validate-drill-plan),然后在 .pre-commit-config.yaml 中引用:

repos:
  - repo: local
    hooks:
      - id: check-drill-plan
        name: 检查演练计划文件
        entry: validate_plan.py
        language: script
        files: 'drill-plan\.(md|yaml|json)$'

这种方式让钩子的安装、更新和共享变得更简单。

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