mcpField
G
git-hooks-automation

git-hooks-automation

github.com/sickn33测试与质量48.7k77 次安装今天更新
代码仓库

关于 git-hooks-automation

用于配置 Git hooks、在开发过程中运行代码检查的实用技能。内容涵盖原生 hooks、Husky 与 lint-staged、pre-commit、自定义脚本及 CI 验证,适合开发者和团队。

主要功能

  1. 01配置 pre-commit 和 pre-push hooks
  2. 02用 lint-staged 检查暂存文件
  3. 03执行提交消息规范检查
  4. 04设置 Husky 或 pre-commit
  5. 05在 CI 中验证 hooks

适用场景

  1. 01在提交前添加 lint 和格式化
  2. 02在推送前运行测试
  3. 03采用或迁移 Git hook 配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill git-hooks-automation

安装后在 Claude Code 中输入/git-hooks-automation确认已加载。

详细介绍

Git 钩子自动化

在 Git 层面自动执行代码质量检查。在提交和推送进入 CI 流水线之前设置钩子,执行 lint、格式化、测试和验证——几秒内发现问题,而不是等上几分钟。

何时使用此技能

  • 用户要求“设置 Git 钩子”或“添加 pre-commit 钩子”
  • 配置 Husky、lint-staged 或 pre-commit 框架
  • 强制执行提交消息规范(Conventional Commits、commitlint)
  • 在提交前自动运行 lint、格式化或类型检查
  • 为测试运行程序设置 pre-push 钩子
  • 从 Husky v4 迁移到 v9+,或从头开始采用钩子
  • 用户提到“pre-commit”、“commit-msg”、“pre-push”、“lint-staged”或“githooks”

Git 钩子基础

Git 钩子是在 Git 工作流的特定时点自动运行的脚本。它们位于 .git/hooks/ 中,默认不纳入版本控制——这正是 Husky 这类工具存在的原因。

钩子类型及触发时机
钩子触发时机常见用途
pre-commit创建提交之前对暂存文件运行 lint、格式化和类型检查
prepare-commit-msg默认消息生成后、编辑器打开前自动填充提交模板
commit-msg用户编写提交消息后强制执行提交消息格式
post-commit创建提交后通知、日志记录
pre-push推送到远程之前运行测试、检查分支策略
pre-rebase开始变基之前阻止在受保护分支上变基
post-merge合并完成后安装依赖、运行迁移
post-checkout检出或切换后安装依赖、重新构建资源
原生 Git 钩子(无框架)
# Create a pre-commit hook manually
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
set -e

# Prefer installed lint-staged: it handles filenames and partially staged files.
# Do not run whole-file fixes followed by git add: that can stage unrelated edits.
npx --no -- lint-staged
EOF
chmod +x .git/hooks/pre-commit

问题:.git/hooks/ 仅存在于本地,不会与团队共享。请改用框架。

Husky + lint-staged(Node.js 项目)

这是 JavaScript/TypeScript 项目的现代标准。Husky 管理 Git 钩子;lint-staged 只对暂存文件运行命令,从而提升速度。

快速设置(Husky v9+)
# Install
npm install --save-dev husky lint-staged

# Initialize Husky (creates .husky/ directory)
npx husky init

# The init command creates a pre-commit hook — edit it:
echo "npx lint-staged" > .husky/pre-commit
在 package.json 中配置 lint-staged
{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix --max-warnings=0",
      "prettier --write"
    ],
    "*.{css,scss}": [
      "prettier --write",
      "stylelint --fix"
    ],
    "*.{json,md,yml,yaml}": [
      "prettier --write"
    ]
  }
}
添加提交消息 lint
# Install commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional

# Create commitlint config
cat > commitlint.config.js << 'EOF'
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor',
      'perf', 'test', 'build', 'ci', 'chore', 'revert'
    ]],
    'subject-max-length': [2, 'always', 72],
    'body-max-line-length': [2, 'always', 100]
  }
};
EOF

# Add commit-msg hook
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
添加 Pre-Push 钩子
# Run tests before pushing
echo "npm test" > .husky/pre-push
完整的 Husky 目录结构
project/
├── .husky/
│   ├── pre-commit        # npx lint-staged
│   ├── commit-msg        # npx --no -- commitlint --edit $1
│   └── pre-push          # npm test
├── commitlint.config.js
├── package.json          # lint-staged config here
└── ...

pre-commit 框架(Python / 多语言项目)

与语言无关的框架,适用于任何项目。钩子以 YAML 定义,并在隔离环境中运行。

设置
# Install (Python required)
pip install pre-commit

# Create config
cat > .pre-commit-config.yaml << 'EOF'
repos:
  # Built-in checks
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: check-added-large-files
        args: ['--maxkb=500']
      - id: check-merge-conflict
      - id: detect-private-key

  # Python formatting
  - repo: https://github.com/psf/black
    rev: 24.4.2
    hooks:
      - id: black

  # Python linting
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.4
    hooks:
      - id: ruff
        args: ['--fix']
      - id: ruff-format

  # Shell script linting
  - repo: https://github.com/shellcheck-py/shellcheck-py
    rev: v0.10.0.1
    hooks:
      - id: shellcheck

  # Commit message format
  - repo: https://github.com/compilerla/conventional-pre-commit
    rev: v3.2.0
    hooks:
      - id: conventional-pre-commit
        stages: [commit-msg]
EOF

# Install hooks into .git/hooks/
pre-commit install
pre-commit install --hook-type commit-msg

# Run against all files (first time)
pre-commit run --all-files
常用命令
pre-commit install              # Install hooks
pre-commit run --all-files      # Run on everything (CI or first setup)
pre-commit autoupdate           # Update hook versions
pre-commit run <hook-id>        # Run a specific hook
pre-commit clean                # Clear cached environments

钩子会运行本地代码;安装前请检查第三方钩子和固定的修订版本。本地钩子可以绕过,不能作为合并授权。下面的便携式自定义示例有意简化:按行处理路径会导致特殊文件名出错;工作树中的文件大小与暂存区 blob 的大小不同;扫描 diff 上下文可能匹配已删除行或上下文行,也可能泄露机密。请使用可安全处理 NUL 字符的暂存区 blob 检查方式,并报告文件名和规则,切勿打印匹配到的机密值。

自定义钩子脚本(任意语言)

对于未使用 Node 或 Python 的项目,可直接用 shell 编写钩子。

便携式 Pre-Commit 钩子
#!/bin/sh
# .githooks/pre-commit — Team-shared hooks directory
set -e

echo "=== Pre-Commit Checks ==="

# 1. Prevent commits to main/master
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "detached")
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
  echo "❌ Direct commits to $BRANCH are not allowed. Use a feature branch."
  exit 1
fi

# 2. Check for debugging artifacts
if git diff --cached --diff-filter=ACM | grep -nE '(console\.log|debugger|binding\.pry|import pdb)' > /dev/null 2>&1; then
  echo "⚠️  Debug statements found in staged files:"
  git diff --cached --diff-filter=ACM | grep -nE '(console\.log|debugger|binding\.pry|import pdb)'
  echo "Review the staged changes and follow repository policy."
  exit 1
fi

# 3. Check for large files (>1MB)
LARGE_FILES=$(git diff --cached --name-only --diff-filter=ACM | while read f; do
  size=$(wc -c < "$f" 2>/dev/null || echo 0)
  if [ "$size" -gt 1048576 ]; then echo "$f ($((size/1024))KB)"; fi
done)
if [ -n "$LARGE_FILES" ]; then
  echo "❌ Large files detected:"
  echo "$LARGE_FILES"
  exit 1
fi

# 4. Check for secrets patterns
if git diff --cached --diff-filter=ACM | grep -nEi '(AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{48}|ghp_[a-zA-Z0-9]{36}|password\s*=\s*["\x27][^"\x27]+["\x27])' > /dev/null 2>&1; then
  echo "🚨 Potential secrets detected in staged changes! Review before committing."
  exit 1
fi

echo "✅ All pre-commit checks passed"
通过 core.hooksPath 共享自定义钩子
# In your repo, set a shared hooks directory
git config core.hooksPath .githooks

# Add to project setup docs or Makefile
# Makefile
setup:
	git config core.hooksPath .githooks
	chmod +x .githooks/*

CI 集成

钩子是第一道防线,但 CI 才是最终依据。

在 CI 中运行 pre-commit(GitHub Actions)
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - uses: pre-commit/[email protected]
在 CI 中运行 lint-staged(仅验证)
# Validate that lint-staged would pass (catch bypassed hooks)
name: Lint Check
on: [pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx eslint . --max-warnings=0
      - run: npx prettier --check .

常见问题及修复方法

钩子未运行
症状原因修复方法
钩子被静默跳过未安装到 .git/hooks/运行 npx husky init 或 pre-commit install
“权限被拒绝”钩子文件不可执行chmod +x .husky/pre-commit
钩子运行了,但不是预期的钩子旧设置遗留了过时钩子检查 git config core.hooksPath,并在针对性修复前保留无关钩子
本地正常,CI 中失败Node/Python 版本不同在 CI 配置中固定版本
性能问题
// ❌ Slow: runs on ALL files every commit
{
  "scripts": {
    "precommit": "eslint src/ && prettier --write src/"
  }
}

// ✅ Fast: lint-staged runs ONLY on staged files
{
  "lint-staged": {
    "*.{js,ts}": ["eslint --fix", "prettier --write"]
  }
}
绕过钩子(必要时)
# Skip all hooks for a single commit
git commit --no-verify -m "wip: quick save"

# Skip pre-push only
git push --no-verify

# Skip specific pre-commit hooks
SKIP=eslint git commit -m "fix: update config"

警告:应尽量避免绕过钩子。如果团队经常绕过钩子,说明钩子运行太慢或限制太严格——请修复它们。

迁移指南

Husky v4 → v9 迁移
# 1. Remove old Husky
npm uninstall husky
# Back up and inspect existing .husky scripts; remove only obsolete generated files

# 2. Remove old config from package.json
# Delete "husky": { "hooks": { ... } } section

# 3. Install fresh
npm install --save-dev husky
npx husky init

# 4. Recreate hooks
echo "npx lint-staged" > .husky/pre-commit
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg

# 5. Clean up — old Husky used package.json config,
#    new Husky uses .husky/ directory with plain scripts
在现有项目中采用钩子
# Step 1: Start with formatting only (low friction)
# lint-staged config:
{ "*.{js,ts}": ["prettier --write"] }

# Step 2: Add linting after team adjusts (1-2 weeks later)
{ "*.{js,ts}": ["eslint --fix", "prettier --write"] }

# Step 3: Add commit message linting
# Step 4: Add pre-push test runner

# Gradual adoption prevents team resistance

核心原则

  • 仅处理暂存文件 — 切勿在每次提交时检查整个代码库
  • 尽可能自动修复 — --fix 标志可减少开发者的阻碍
  • 快速钩子 — 提交前钩子应在 < 5 秒内完成
  • 明确报错 — 提供清晰且可操作的修复建议
  • 团队共享 — 使用 Husky 或 core.hooksPath,将钩子纳入版本控制
  • CI 作为后备 — 钩子旨在提供便利;CI 才是强制执行手段
  • 逐步采用 — 从格式化开始,再添加代码检查,最后添加测试

相关技能

  • @codebase-audit-pre-push - 推送到 GitHub 前进行深度审查
  • @verification-before-completion - 声明工作完成前进行验证
  • @bash-pro - 用于编写自定义钩子的高级 Shell 脚本
  • @github-actions-templates - CI/CD 工作流模板

限制

  • 仅当任务明确符合上述范围时,才使用此技能。
  • 不要将输出视为针对特定环境的验证、测试或专家审查的替代品。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请暂停并请求澄清。

评论

支持 Markdown