关于 git-hooks-automation
用于配置 Git hooks、在开发过程中运行代码检查的实用技能。内容涵盖原生 hooks、Husky 与 lint-staged、pre-commit、自定义脚本及 CI 验证,适合开发者和团队。
主要功能
- 01配置 pre-commit 和 pre-push hooks
- 02用 lint-staged 检查暂存文件
- 03执行提交消息规范检查
- 04设置 Husky 或 pre-commit
- 05在 CI 中验证 hooks
适用场景
- 01在提交前添加 lint 和格式化
- 02在推送前运行测试
- 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 工作流模板
限制
- 仅当任务明确符合上述范围时,才使用此技能。
- 不要将输出视为针对特定环境的验证、测试或专家审查的替代品。
- 如果缺少必要的输入、权限、安全边界或成功标准,请暂停并请求澄清。