name: commit-hygiene description: Atomic commits, PR size limits, commit thresholds, stacked PRs
Commit Hygiene Skill
Load with: base.md
Purpose: Keep commits atomic, PRs reviewable, and git history clean. Advise when it’s time to commit before changes become too large.
Core Philosophy
┌─────────────────────────────────────────────────────────────────┐
│ 原子提交 │
│ ───────────────────────────────────────────────────────── │
│ 每次提交一个逻辑更改。 │
│ 每个提交应该是自包含且可部署的。 │
│ 如果你需要用“和”来描述它,请拆分它。 │
├─────────────────────────────────────────────────────────────────┤
│ 小PR赢 │
│ ───────────────────────────────────────────────────────── │
│ < 400行更改 = 在 < 1小时内审查 │
│ > 1000行 = 可能被草率批准或放弃 │
│ 更小的PR = 更快的审查,更少的错误,更容易的回滚 │
├─────────────────────────────────────────────────────────────────┤
│ 早提交,常提交 │
│ ───────────────────────────────────────────────────────────── │
│ 工作代码?提交它。 │
│ 测试通过?提交它。 │
│ 不要等到“完成” - 在每个稳定点提交。 │
└─────────────────────────────────────────────────────────────────┘
Commit Size Thresholds
Warning Thresholds (Time to Commit!)
| Metric | Yellow Zone | Red Zone | Action |
|---|---|---|---|
| Files changed | 5-10 files | > 10 files | 立即提交 |
| Lines added | 150-300 lines | > 300 lines | 立即提交 |
| Lines deleted | 100-200 lines | > 200 lines | 立即提交 |
| Total changes | 250-400 lines | > 400 lines | 立即提交 |
| Time since last commit | 30-60 min | > 60 min | 考虑提交 |
Ideal Commit Size
┌─────────────────────────────────────────────────────────────────┐
│ 理想提交 │
│ ───────────────────────────────────────────────────────────── │
│ 文件:1-5 │
│ 行数:50-200总更改 │
│ 范围:单一逻辑工作单元 │
│ 消息:描述一件事情 │
└─────────────────────────────────────────────────────────────────┘
Check Current State (Run Frequently)
Quick Status Check
# 查看更改(暂存+未暂存)
git status --short
# 计算文件和行数更改
git diff --stat
git diff --cached --stat # 仅暂存
# 获取总数
git diff --shortstat
# 示例输出:8文件更改,245插入(+),32删除(-)
Detailed Change Analysis
# 全部差异摘要及文件名
git diff --stat HEAD
# 仅数字
git diff --numstat HEAD | awk '{add+=$1; del+=$2} END {print "+"add" -"del" total:"add+del}'
# 文件更改计数
git status --porcelain | wc -l
Pre-Commit Check Script
#!/bin/bash
# scripts/check-commit-size.sh
# 阈值
MAX_FILES=10
MAX_LINES=400
WARN_FILES=5
WARN_LINES=200
# 获取统计数据
FILES=$(git status --porcelain | wc -l | tr -d ' ')
STATS=$(git diff --shortstat HEAD 2>/dev/null)
INSERTIONS=$(echo "$STATS" | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' || echo 0)
DELETIONS=$(echo "$STATS" | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' || echo 0)
TOTAL=$((INSERTIONS + DELETIONS))
echo "📊 当前更改:$FILES文件,+$INSERTIONS -$DELETIONS ($TOTAL总行数)"
# 检查阈值
if [ "$FILES" -gt "$MAX_FILES" ] || [ "$TOTAL" -gt "$MAX_LINES" ]; then
echo "🔴 红色区域:立即提交!更改过大。"
echo " 考虑拆分为多个提交。"
exit 1
elif [ "$FILES" -gt "$WARN_FILES" ] || [ "$TOTAL" -gt "$WARN_LINES" ]; then
echo "🟡 警告:更改越来越大。尽快提交。"
exit 0
else
echo "🟢 良好:更改在健康限制内。"
exit 0
fi
When to Commit
Commit Triggers (Any One = Commit)
| Trigger | Example |
|---|---|
| Test passes | 测试刚刚变绿 → 提交 |
| Feature complete | 完成一个功能 → 提交 |
| Refactor done | 跨文件重命名变量 → 提交 |
| Bug fixed | 修复问题 → 提交 |
| Before switching context | 即将处理其他事情 → 提交 |
| Clean compile | 代码编译/检查干净 → 提交 |
| Threshold hit | > 5文件或> 200行 → 提交 |
Commit Immediately If
- ✅ 测试通过后变为红色
- ✅ 即将进行“大更改”
- ✅ 编码超过30分钟
- ✅ 即将尝试一些有风险的操作
- ✅ 当前状态是“工作”的
Don’t Wait For
- ❌ “完美”的代码
- ❌ 所有功能完成
- ❌ 全部测试覆盖
- ❌ 来自你自己的代码审查
- ❌ 文档完成
Atomic Commit Patterns
Good Atomic Commits
✅ "Add email validation to signup form"
- 3文件:validator.ts, signup.tsx, signup.test.ts
- 120行更改
- 单一目的:电子邮件验证
✅ "Fix null pointer in user lookup"
- 2文件:userService.ts, userService.test.ts
- 25行更改
- 单一目的:修复一个bug
✅ "Refactor: Extract PaymentProcessor class"
- 4文件:payment.ts → paymentProcessor.ts + 类型
- 180行更改
- 单一目的:重构
Bad Commits (Too Large)
❌ "Add authentication, fix bugs, update styles"
- 25文件更改
- 800行更改
- 混合了多个目的
❌ "WIP"
- 未知范围
- 没有明确的目的
- 难以审查/回滚
❌ "Updates"
- 15文件更改
- 混合了功能、修复和重构
- 无法正确审查
Splitting Large Changes
Strategy 1: By Layer
不要一个提交包含:
- API端点 + 数据库迁移 + 前端 + 测试
拆分为:
1. "Add users table migration"
2. "Add User model and repository"
3. "Add GET /users endpoint"
4. "Add UserList component"
5. "Add integration tests for user flow"
Strategy 2: By Feature Slice
不要一个提交包含:
- 用户的所有CRUD操作
拆分为:
1. "Add create user functionality"
2. "Add read user functionality"
3. "Add update user functionality"
4. "Add delete user functionality"
Strategy 3: Refactor First
不要:
- 功能+重构混合
拆分为:
1. "Refactor: Extract validation helpers"(无行为变化)
2. "Add email validation using new helpers"(新功能)
Strategy 4: By Risk Level
不要一个提交包含:
- 安全更改 + 风险更改一起
拆分为:
1. "Update dependencies"(安全,隔离)
2. "Migrate to new API version"(风险,分开)
PR Size Guidelines
Optimal PR Size
| Metric | Optimal | Acceptable | Too Large |
|---|---|---|---|
| Files | 1-10 | 10-20 | > 20 |
| Lines changed | 50-200 | 200-400 | > 400 |
| Commits | 1-5 | 5-10 | > 10 |
| Review time | < 30 min | 30-60 min | > 60 min |
PR Size vs Defect Rate
┌─────────────────────────────────────────────────────────────────┐
│ 研究发现 (Google, Microsoft研究) │
│ ───────────────────────────────────────────────────────── │
│ PRs < 200行:15%缺陷率 │
│ PRs 200-400行:23%缺陷率 │
| PRs > 400行:40%+缺陷率 │
│ │
│ 超过200-400行后审查质量急剧下降。 │
│ 大PRs得到“LGTM”橡皮图章,而不是真正的审查。 │
└─────────────────────────────────────────────────────────────────┘
When PR is Too Large
# 创建PR前检查大小
git diff main --stat
git diff main --shortstat
# 如果太大,考虑:
# 1. 拆分为多个PR(堆叠PR)
# 2. 创建功能标志并逐步合并
# 3. 使用草稿PR进行早期反馈
Commit Message Format
Structure
<type>: <description> (50 chars max)
[optional body - wrap at 72 chars]
[optional footer]
Types
| Type | Use For |
|---|---|
feat |
新功能 |
fix |
Bug修复 |
refactor |
代码更改,既不修复也不添加 |
test |
添加/更新测试 |
docs |
仅文档 |
style |
格式化,无代码更改 |
chore |
构建,配置,依赖 |
Examples
feat: Add email validation to signup form
fix: Prevent null pointer in user lookup
refactor: Extract PaymentProcessor class
test: Add integration tests for checkout flow
chore: Update dependencies to latest versions
Git Workflow Integration
Pre-Commit Hook for Size Check
#!/bin/bash
# .git/hooks/pre-commit
MAX_LINES=400
MAX_FILES=15
FILES=$(git diff --cached --name-only | wc -l | tr -d ' ')
STATS=$(git diff --cached --shortstat)
INSERTIONS=$(echo "$STATS" | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' || echo 0)
DELETIONS=$(echo "$STATS" | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' || echo 0)
TOTAL=$((INSERTIONS + DELETIONS))
if [ "$TOTAL" -gt "$MAX_LINES" ]; then
echo "❌ 提交太大:$TOTAL行(最大:$MAX_LINES)"
echo " 考虑拆分为更小的提交。"
echo " 使用 'git add -p' 进行部分暂存。"
exit 1
fi
if [ "$FILES" -gt "$MAX_FILES" ]; then
echo "❌ 文件太多:$FILES(最大:$MAX_FILES)"
echo " 考虑拆分为更小的提交。"
exit 1
fi
echo "✅ 提交大小OK:$FILES文件,$TOTAL行"
Partial Staging (Split Large Changes)
# 交互式地暂存特定块
git add -p
# 暂存特定文件
git add path/to/specific/file.ts
# 预览暂存
git add -N file.ts # 意图添加
git diff # 查看将添加的内容
git add file.ts # 实际添加
Unstage If Too Large
# 取消暂存所有内容
git reset HEAD
# 取消暂存特定文件
git reset HEAD path/to/file.ts
# 仅暂存本次提交所需的内容
git add -p
Claude Integration
Periodic Check During Development
Claude应在每次重大更改后运行此检查:
# 快速状态
git diff --shortstat HEAD
Claude建议提交的阈值:
| 条件 | Claude操作 |
|---|---|
| > 5文件更改 | 建议:“考虑提交当前更改” |
| > 200行更改 | 建议:“更改越来越大,建议提交” |
| > 10文件或> 400行 | 警告:“⚠️现在提交,以免更改变得难以管理” |
| 测试刚刚通过 | 建议:“好的检查点 - 提交这些通过的测试” |
| 重构完成 | 建议:“重构完成 - 在添加功能前提交” |
Claude提交提醒消息
📊 状态:7文件更改,+180 -45(225总数)
💡 接近提交阈值。考虑提交当前工作。
---
📊 状态:12文件更改,+320 -80(400总数)
⚠️ 更改大!现在提交以保持PR可审查。
建议提交:"feat: Add user authentication flow"
---
📊 状态:3文件更改,+85 -10(95总数)
✅ 测试通过。提交的好时机!
建议提交:"fix: Validate email format on signup"
Stacked PRs (For Large Features)
当一个功能确实很大时,使用堆叠PR:
┌─────────────────────────────────────────────────────────────────┐
│ 堆叠PR模式 │
│ ───────────────────────────────────────────────────────────── │
│ │
│ main ─────────────────────────────────────────────────────────│
│ └── PR #1: 数据库模式(200行)← 首先审查 │
│ └── PR #2: API端点(250行)← 第二次审查 │
│ └── PR #3: 前端(300行)← 第三次审查 │
│ │
│ 每个PR都可以独立审查。 │
│ 合并顺序:#1 → #2 → #3 │
└─────────────────────────────────────────────────────────────────┘
创建堆叠PR
# 创建基础分支
git checkout -b feature/auth-schema
# ... 做更改 ...
git commit -m "feat: Add users table schema"
git push -u origin feature/auth-schema
gh pr create --base main --title "feat: Add users table schema"
# 从第一个创建下一个分支
git checkout -b feature/auth-api
# ... 做更改 ...
git commit -m "feat: Add authentication API endpoints"
git push -u origin feature/auth-api
gh pr create --base feature/auth-schema --title "feat: Add auth API endpoints"
# 以此类推...
Checklist
提交前
- [ ] 更改是为了一个逻辑目的
- [ ] 测试通过(如适用)
- [ ] 代码检查/类型检查通过
- [ ] < 10文件更改
- [ ] < 400行总数
- [ ] 提交消息描述一件事情
创建PR前
- [ ] 总行数 < 400(理想 < 200)
- [ ] 所有提交都是原子的
- [ ] 没有"WIP"或"fixup"提交
- [ ] PR标题描述更改
- [ ] 描述解释原因,而不仅仅是什么
红旗(停下来拆分)
- ❌ 提交消息需要"和"
- ❌ 一个提交中 > 10文件
- ❌ 一个提交中 > 400行
- ❌ 混合了功能、修复和重构
- ❌ “我稍后再清理这个”
快速参考
阈值
文件: ≤ 5 = 🟢 | 6-10 = 🟡 | > 10 = 🔴
行数: ≤ 200 = 🟢 | 201-400 = 🟡 | > 400 = 🔴
时间: ≤ 30分钟 = 🟢 | 30-60分钟 = 🟡 | > 60分钟 = 🔴
命令
# 快速状态
git diff --shortstat HEAD
# 详细文件列表
git diff --stat HEAD
# 部分暂存
git add -p
# PR前检查
git diff main --shortstat
立即提交如果
- ✅ 测试刚刚通过
- ✅ > 200行更改
- ✅ > 5文件更改
- ✅ 即将切换任务
- ✅ 当前状态是"工作"的