Git Hooks 企业级配置
完整的 Git Hooks 配置方案,包含代码质量检查、提交规范、自动化测试等企业级实践。
🎯 Git Hooks 概述
Git Hooks 是在 Git 执行特定事件时触发的脚本,用于自动化代码质量检查和规范执行。
核心 Hooks 类型
- pre-commit: 提交前执行,用于代码质量检查
- commit-msg: 提交信息检查,确保符合规范
- pre-push: 推送前执行,运行测试和构建检查
- post-merge: 合并后执行,自动安装依赖等
🛠️ 工具链配置
1. Husky 配置
bash
# 安装 Husky
npm install husky -D
# 初始化 Husky
npx husky install
# 设置 package.json 脚本
npm pkg set scripts.prepare="husky install"
2. 项目结构
.husky/
├── _/ # Husky 内部文件
├── pre-commit # 提交前钩子
├── commit-msg # 提交信息钩子
├── pre-push # 推送前钩子
└── post-merge # 合并后钩子
📝 Hooks 实现
1. pre-commit 钩子
bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo "🔍 Running pre-commit checks..."
# 1. 运行 lint-staged
npx lint-staged
# 2. 类型检查(如果使用 TypeScript)
if [ -f "tsconfig.json" ]; then
echo "🔍 Running TypeScript type check..."
npx tsc --noEmit
fi
# 3. 运行单元测试
echo "🧪 Running unit tests..."
npm run test:unit
# 4. 检查构建是否成功
echo "🏗️ Checking build..."
npm run build:check
echo "✅ Pre-commit checks passed!"
2. commit-msg 钩子
bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo "🔍 Checking commit message format..."
# 使用 commitlint 检查提交信息
npx --no-install commitlint --edit "$1"
echo "✅ Commit message format is valid!"
3. pre-push 钩子
bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo "🔍 Running pre-push checks..."
# 1. 运行完整测试套件
echo "🧪 Running full test suite..."
npm run test
# 2. 运行 E2E 测试
echo "🎭 Running E2E tests..."
npm run test:e2e
# 3. 检查构建
echo "🏗️ Running production build..."
npm run build
# 4. 安全检查
echo "🔒 Running security audit..."
npm audit --audit-level moderate
# 5. 依赖检查
echo "📦 Checking for outdated dependencies..."
npm outdated
echo "✅ Pre-push checks passed!"
4. post-merge 钩子
bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo "🔄 Running post-merge tasks..."
# 检查 package.json 是否有变化
changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
check_run() {
echo "$changed_files" | grep --quiet "$1" && eval "$2"
}
# 如果 package.json 发生变化,重新安装依赖
check_run "package.json\|pnpm-lock.yaml" "echo '📦 Dependencies changed, running install...' && pnpm install"
# 如果数据库迁移文件发生变化,运行迁移
check_run "migrations/" "echo '🗄️ Running database migrations...' && npm run db:migrate"
# 如果环境配置发生变化,提醒开发者
check_run ".env.example" "echo '⚠️ Environment configuration changed, please update your .env file'"
echo "✅ Post-merge tasks completed!"
🔧 lint-staged 配置
package.json 配置
json
{
"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": [
"eslint --fix",
"prettier --write"
],
"*.{css,scss,less}": [
"stylelint --fix",
"prettier --write"
],
"*.{json,md,yml,yaml}": [
"prettier --write"
],
"*.{png,jpg,jpeg,gif,svg}": [
"imagemin-lint-staged"
]
}
}
独立配置文件
javascript
// lint-staged.config.js
module.exports = {
// JavaScript/TypeScript 文件
'*.{js,jsx,ts,tsx,vue}': [
'eslint --fix',
'prettier --write',
'git add'
],
// 样式文件
'*.{css,scss,less,styl}': [
'stylelint --fix',
'prettier --write',
'git add'
],
// 配置文件
'*.{json,md,yml,yaml}': [
'prettier --write',
'git add'
],
// 图片优化
'*.{png,jpg,jpeg,gif,svg}': [
'imagemin-lint-staged',
'git add'
],
// 包管理文件
'package.json': [
'sort-package-json',
'prettier --write',
'git add'
]
}
📋 Commitlint 配置
基础配置
javascript
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// 类型枚举
'type-enum': [
2,
'always',
[
'feat', // 新功能
'fix', // 修复
'docs', // 文档
'style', // 格式
'refactor', // 重构
'perf', // 性能优化
'test', // 测试
'chore', // 构建过程或辅助工具的变动
'revert', // 回滚
'build', // 构建系统或外部依赖项的更改
'ci' // CI 配置文件和脚本的更改
]
],
// 主题长度限制
'subject-max-length': [2, 'always', 50],
// 主题不能为空
'subject-empty': [2, 'never'],
// 主题格式
'subject-case': [2, 'always', 'lower-case'],
// 类型不能为空
'type-empty': [2, 'never'],
// 类型格式
'type-case': [2, 'always', 'lower-case']
}
}
自定义规则
javascript
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// 自定义类型
'type-enum': [
2,
'always',
[
'feat', // ✨ 新功能
'fix', // 🐛 修复
'docs', // 📝 文档
'style', // 💄 格式
'refactor', // ♻️ 重构
'perf', // ⚡ 性能优化
'test', // ✅ 测试
'chore', // 🔧 构建/工具
'revert', // ⏪ 回滚
'build', // 📦 构建
'ci', // 👷 CI
'release' // 🔖 发布
]
],
// 范围枚举(可选)
'scope-enum': [
2,
'always',
[
'core',
'ui',
'api',
'auth',
'router',
'store',
'utils',
'config',
'deps'
]
],
// 主题必须以小写开头
'subject-case': [2, 'always', 'lower-case'],
// 主题不能以句号结尾
'subject-full-stop': [2, 'never', '.'],
// 正文每行最大长度
'body-max-line-length': [2, 'always', 100],
// 页脚每行最大长度
'footer-max-line-length': [2, 'always', 100]
}
}
🎨 提交信息模板
Commitizen 配置
bash
# 安装 Commitizen
npm install commitizen cz-conventional-changelog -D
# 配置 package.json
npm pkg set scripts.commit="cz"
npm pkg set config.commitizen.path="cz-conventional-changelog"
自定义提交模板
javascript
// .cz-config.js
module.exports = {
types: [
{ value: 'feat', name: '✨ feat: 新功能' },
{ value: 'fix', name: '🐛 fix: 修复' },
{ value: 'docs', name: '📝 docs: 文档变更' },
{ value: 'style', name: '💄 style: 代码格式' },
{ value: 'refactor', name: '♻️ refactor: 重构' },
{ value: 'perf', name: '⚡ perf: 性能优化' },
{ value: 'test', name: '✅ test: 测试' },
{ value: 'chore', name: '🔧 chore: 构建/工具' },
{ value: 'revert', name: '⏪ revert: 回滚' },
{ value: 'build', name: '📦 build: 构建系统' },
{ value: 'ci', name: '👷 ci: CI 配置' }
],
scopes: [
{ name: 'core' },
{ name: 'ui' },
{ name: 'api' },
{ name: 'auth' },
{ name: 'router' },
{ name: 'store' },
{ name: 'utils' },
{ name: 'config' },
{ name: 'deps' }
],
messages: {
type: '选择提交类型:',
scope: '选择修改范围 (可选):',
customScope: '请输入修改范围:',
subject: '请简要描述提交 (必填):',
body: '请输入详细描述 (可选):',
breaking: '列出任何破坏性变更 (可选):',
footer: '请输入要关闭的 issue (可选):',
confirmCommit: '确认使用以上信息提交?'
},
allowCustomScopes: true,
allowBreakingChanges: ['feat', 'fix'],
subjectLimit: 50,
breaklineChar: '|',
footerPrefix: 'ISSUES CLOSED:'
}
🚀 高级配置
条件执行
bash
#!/usr/bin/env sh
# pre-commit 条件执行示例
# 只在特定分支执行完整检查
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" = "main" ] || [ "$branch" = "develop" ]; then
echo "🔍 Running full checks on $branch branch..."
npm run test:full
else
echo "🔍 Running basic checks on $branch branch..."
npm run test:unit
fi
性能优化
bash
#!/usr/bin/env sh
# 并行执行多个检查
# 后台运行测试
npm run test:unit &
TEST_PID=$!
# 后台运行 lint
npx lint-staged &
LINT_PID=$!
# 等待所有任务完成
wait $TEST_PID
wait $LINT_PID
echo "✅ All checks completed!"
💡 最佳实践
1. 渐进式引入
bash
# 开始时只启用基础检查
echo "npx lint-staged" > .husky/pre-commit
# 逐步增加更多检查
echo "npm run test:unit" >> .husky/pre-commit
echo "npm run type-check" >> .husky/pre-commit
2. 团队协作
json
{
"scripts": {
"prepare": "husky install",
"hooks:install": "husky install && chmod +x .husky/*",
"hooks:uninstall": "husky uninstall"
}
}
3. CI/CD 集成
yaml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run the same checks as pre-commit
run: |
npx lint-staged
npm run test
npm run build
这套 Git Hooks 配置确保了代码质量的一致性,提高了团队协作效率,是企业级项目的必备配置。