
关于
使用 Husky、lint-staged、pre-commit 框架和 commitlint 掌握 Git 钩子设置。自动化代码质量检查和提交规范。
name: git-hooks-automation description: "掌握使用 Husky、lint-staged、pre-commit 框架和 commitlint 设置 Git 钩子。在代码到达 CI 之前自动化代码质量门控、格式化、代码检查和提交消息规范。" risk: safe source: community date_added: "2026-03-07"
Git 钩子自动化
在 Git 层面自动执行代码质量管控。设置钩子在提交和推送到达 CI 流水线之前进行代码检查、格式化、测试和验证——将问题发现时间从几分钟缩短到几秒。
何时使用此技能
- 用户要求"设置 git 钩子"或"添加 pre-commit 钩子"
- 配置 Husky、lint-staged 或 pre-commit 框架
- 强制执行提交消息规范(Conventional Commits、commitlint)
- 在提交前自动化代码检查、格式化或类型检查
- 设置 pre-push 钩子运行测试
- 从 Husky v4 迁移到 v9+ 或从零开始引入钩子
- 用户提到 "pre-commit"、"commit-msg"、"pre-push"、"lint-staged" 或 "githooks"
Git 钩子基础知识
Git 钩子是在 Git 工作流特定节点自动运行的脚本。它们位于 .git/hooks/ 目录中,默认不受版本控制——这就是 Husky 等工具存在的原因。
钩子类型及触发时机
| 钩子 | 触发时机 | 常见用途 |
|------|----------|----------|
| pre-commit | 创建提交之前 | 对暂存文件进行代码检查、格式化、类型检查 |
| 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
# Run linter on staged files only
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|jsx|tsx)$' || true)
if [ -n "$STAGED_FILES" ]; then
echo "Linting staged files..."
echo "$STAGED_FILES" | xargs npx eslint --fix
echo "$STAGED_FILES" | xargs git add # Re-stage after fixes
fi
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"
]
}
}
添加提交消息检查
# 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 配置在此
└── ...
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]
EOF
# Install hooks into .git/hooks/
pre-commit install
# Run on all files (first time)
pre-commit run --all-files
常用命令
# Skip hooks temporarily
git commit --no-verify -m "wip: quick save"
# Update hook versions
pre-commit autoupdate
# Run specific hook
pre-commit run black --all-files
故障排查
| 问题 | 解决方案 |
|------|----------|
| 钩子未运行 | 运行 npx husky install 或 pre-commit install |
| lint-staged 卡住 | 删除 .git/index.lock 后重试 |
| 钩子太慢 | 仅对暂存文件运行检查,将完整测试移至 pre-push |
| 权限被拒绝 | 运行 chmod +x .husky/pre-commit |
| CI 中钩子失败 | 在 CI 环境中设置 HUSKY=0 禁用钩子 |

