<< All versions
Skill v1.0.0
currentAutomated scan100/100alinaqi/maggy/commit-hygiene
──Details
PublishedOctober 1, 2026 at 08:11 PM
Content Hashsha256:1807a34d461ed3c5...
Git SHA72a456e6ccf0
──Files
Files (1 file, 16.5 KB)
SKILL.md16.5 KBactive
SKILL.md · 553 lines · 16.5 KB
version: "1.0.0" name: commit-hygiene description: Atomic commits, PR size limits, commit thresholds, stacked PRs when-to-use: When committing code, creating PRs, or when change set is growing large user-invocable: false effort: low
Commit Hygiene Skill
Purpose: Keep commits atomic, PRs reviewable, and git history clean. Advise when it's time to commit before changes become too large.
Core Philosophy
┌─────────────────────────────────────────────────────────────────┐│ ATOMIC COMMITS ││ ───────────────────────────────────────────────────────────── ││ One logical change per commit. ││ Each commit should be self-contained and deployable. ││ If you need "and" to describe it, split it. │├─────────────────────────────────────────────────────────────────┤│ SMALL PRS WIN ││ ───────────────────────────────────────────────────────────── ││ < 400 lines changed = reviewed in < 1 hour ││ > 1000 lines = likely rubber-stamped or abandoned ││ Smaller PRs = faster reviews, fewer bugs, easier reverts │├─────────────────────────────────────────────────────────────────┤│ COMMIT EARLY, COMMIT OFTEN ││ ───────────────────────────────────────────────────────────── ││ Working code? Commit it. ││ Test passing? Commit it. ││ Don't wait for "done" - commit at every stable point. │└─────────────────────────────────────────────────────────────────┘
Commit Size Thresholds
Warning Thresholds (Time to Commit!)
| Metric | Yellow Zone | Red Zone | Action | |
|---|---|---|---|---|
| Files changed | 5-10 files | > 10 files | Commit NOW | |
| Lines added | 150-300 lines | > 300 lines | Commit NOW | |
| Lines deleted | 100-200 lines | > 200 lines | Commit NOW | |
| Total changes | 250-400 lines | > 400 lines | Commit NOW | |
| Time since last commit | 30-60 min | > 60 min | Consider committing |
Ideal Commit Size
┌─────────────────────────────────────────────────────────────────┐│ IDEAL COMMIT ││ ───────────────────────────────────────────────────────────── ││ Files: 1-5 ││ Lines: 50-200 total changes ││ Scope: Single logical unit of work ││ Message: Describes ONE thing │└─────────────────────────────────────────────────────────────────┘
Check Current State (Run Frequently)
Quick Status Check
bash
# See what's changed (staged + unstaged)git status --short# Count files and lines changedgit diff --statgit diff --cached --stat # Staged only# Get totalsgit diff --shortstat# Example output: 8 files changed, 245 insertions(+), 32 deletions(-)
Detailed Change Analysis
bash
# Full diff summary with file namesgit diff --stat HEAD# Just the numbersgit diff --numstat HEAD | awk '{add+=$1; del+=$2} END {print "+"add" -"del" total:"add+del}'# Files changed countgit status --porcelain | wc -l
Pre-Commit Check Script
bash
#!/bin/bash# scripts/check-commit-size.sh# ThresholdsMAX_FILES=10MAX_LINES=400WARN_FILES=5WARN_LINES=200# Get statsFILES=$(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 "📊 Current changes: $FILES files, +$INSERTIONS -$DELETIONS ($TOTAL total lines)"# Check thresholdsif [ "$FILES" -gt "$MAX_FILES" ] || [ "$TOTAL" -gt "$MAX_LINES" ]; thenecho "🔴 RED ZONE: Commit immediately! Changes are too large."echo " Consider splitting into multiple commits."exit 1elif [ "$FILES" -gt "$WARN_FILES" ] || [ "$TOTAL" -gt "$WARN_LINES" ]; thenecho "🟡 WARNING: Changes getting large. Commit soon."exit 0elseecho "🟢 OK: Changes are within healthy limits."exit 0fi
When to Commit
Commit Triggers (Any One = Commit)
| Trigger | Example | |
|---|---|---|
| Test passes | Just got a test green → commit | |
| Feature complete | Finished a function → commit | |
| Refactor done | Renamed variable across files → commit | |
| Bug fixed | Fixed the issue → commit | |
| Before switching context | About to work on something else → commit | |
| Clean compile | Code compiles/lints clean → commit | |
| Threshold hit | > 5 files or > 200 lines → commit |
Commit Immediately If
- ✅ Tests are passing after being red
- ✅ You're about to make a "big change"
- ✅ You've been coding for 30+ minutes
- ✅ You're about to try something risky
- ✅ The current state is "working"
Don't Wait For
- ❌ "Perfect" code
- ❌ All features done
- ❌ Full test coverage
- ❌ Code review from yourself
- ❌ Documentation complete
Atomic Commit Patterns
Good Atomic Commits
✅ "Add email validation to signup form"- 3 files: validator.ts, signup.tsx, signup.test.ts- 120 lines changed- Single purpose: email validation✅ "Fix null pointer in user lookup"- 2 files: userService.ts, userService.test.ts- 25 lines changed- Single purpose: fix one bug✅ "Refactor: Extract PaymentProcessor class"- 4 files: payment.ts → paymentProcessor.ts + types- 180 lines changed- Single purpose: refactoring
Bad Commits (Too Large)
❌ "Add authentication, fix bugs, update styles"- 25 files changed- 800 lines changed- Multiple purposes mixed❌ "WIP"- Unknown scope- No clear purpose- Hard to review/revert❌ "Updates"- 15 files changed- Mix of features, fixes, refactors- Impossible to review properly
Splitting Large Changes
Strategy 1: By Layer
Instead of one commit with:- API endpoint + database migration + frontend + testsSplit into: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
Instead of one commit with:- All CRUD operations for usersSplit into:1. "Add create user functionality"2. "Add read user functionality"3. "Add update user functionality"4. "Add delete user functionality"
Strategy 3: Refactor First
Instead of:- Feature + refactoring mixedSplit into:1. "Refactor: Extract validation helpers" (no behavior change)2. "Add email validation using new helpers" (new feature)
Strategy 4: By Risk Level
Instead of:- Safe changes + risky changes togetherSplit into:1. "Update dependencies" (safe, isolated)2. "Migrate to new API version" (risky, separate)
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
┌─────────────────────────────────────────────────────────────────┐│ RESEARCH FINDINGS (Google, Microsoft studies) ││ ───────────────────────────────────────────────────────────── ││ PRs < 200 lines: 15% defect rate ││ PRs 200-400 lines: 23% defect rate ││ PRs > 400 lines: 40%+ defect rate ││ ││ Review quality drops sharply after 200-400 lines. ││ Large PRs get "LGTM" rubber stamps, not real reviews. │└─────────────────────────────────────────────────────────────────┘
When PR is Too Large
bash
# Check PR size before creatinggit diff main --statgit diff main --shortstat# If too large, consider:# 1. Split into multiple PRs (stacked PRs)# 2. Create feature flag and merge incrementally# 3. Use draft PR for early feedback
Commit Message Format
Structure
<type>: <description> (50 chars max)[optional body - wrap at 72 chars][optional footer]
Types
| Type | Use For | |
|---|---|---|
feat | New feature | |
fix | Bug fix | |
refactor | Code change that neither fixes nor adds | |
test | Adding/updating tests | |
docs | Documentation only | |
style | Formatting, no code change | |
chore | Build, config, dependencies |
Examples
feat: Add email validation to signup formfix: Prevent null pointer in user lookuprefactor: Extract PaymentProcessor classtest: Add integration tests for checkout flowchore: Update dependencies to latest versions
Git Workflow Integration
Pre-Commit Hook for Size Check
bash
#!/bin/bash# .git/hooks/pre-commitMAX_LINES=400MAX_FILES=15FILES=$(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" ]; thenecho "❌ Commit too large: $TOTAL lines (max: $MAX_LINES)"echo " Consider splitting into smaller commits."echo " Use 'git add -p' for partial staging."exit 1fiif [ "$FILES" -gt "$MAX_FILES" ]; thenecho "❌ Too many files: $FILES (max: $MAX_FILES)"echo " Consider splitting into smaller commits."exit 1fiecho "✅ Commit size OK: $FILES files, $TOTAL lines"
Partial Staging (Split Large Changes)
bash
# Stage specific hunks interactivelygit add -p# Stage specific filesgit add path/to/specific/file.ts# Stage with previewgit add -N file.ts # Intent to addgit diff # See what would be addedgit add file.ts # Actually add
Unstage If Too Large
bash
# Unstage everythinggit reset HEAD# Unstage specific filesgit reset HEAD path/to/file.ts# Stage just what you need for THIS commitgit add -p
Claude Integration
Periodic Check During Development
Claude should run this check after every significant change:
bash
# Quick statusgit diff --shortstat HEAD
Thresholds for Claude to advise committing:
| Condition | Claude Action | |
|---|---|---|
| > 5 files changed | Suggest: "Consider committing current changes" | |
| > 200 lines changed | Suggest: "Changes are getting large, commit recommended" | |
| > 10 files OR > 400 lines | Warn: "⚠️ Commit now before changes become unmanageable" | |
| Test just passed | Suggest: "Good checkpoint - commit these passing tests" | |
| Refactoring complete | Suggest: "Refactoring done - commit before adding features" |
Claude Commit Reminder Messages
📊 Status: 7 files changed, +180 -45 (225 total)💡 Approaching commit threshold. Consider committing current work.---📊 Status: 12 files changed, +320 -80 (400 total)⚠️ Changes are large! Commit now to keep PRs reviewable.Suggested commit: "feat: Add user authentication flow"---📊 Status: 3 files changed, +85 -10 (95 total)✅ Tests passing. Good time to commit!Suggested commit: "fix: Validate email format on signup"
Stacked PRs (For Large Features)
When a feature is genuinely large, use stacked PRs:
┌─────────────────────────────────────────────────────────────────┐│ STACKED PR PATTERN ││ ───────────────────────────────────────────────────────────── ││ ││ main ─────────────────────────────────────────────────────────││ └── PR #1: Database schema (200 lines) ← Review first ││ └── PR #2: API endpoints (250 lines) ← Review second ││ └── PR #3: Frontend (300 lines) ← Review third ││ ││ Each PR is reviewable independently. ││ Merge in order: #1 → #2 → #3 │└─────────────────────────────────────────────────────────────────┘
Creating Stacked PRs
bash
# Create base branchgit checkout -b feature/auth-schema# ... make changes ...git commit -m "feat: Add users table schema"git push -u origin feature/auth-schemagh pr create --base main --title "feat: Add users table schema"# Create next branch FROM the firstgit checkout -b feature/auth-api# ... make changes ...git commit -m "feat: Add authentication API endpoints"git push -u origin feature/auth-apigh pr create --base feature/auth-schema --title "feat: Add auth API endpoints"# And so on...
Checklist
Before Every Commit
- [ ] Changes are for ONE logical purpose
- [ ] Tests pass (if applicable)
- [ ] Lint/typecheck pass
- [ ] < 10 files changed
- [ ] < 400 lines total
- [ ] Commit message describes ONE thing
Before Creating PR
- [ ] Total lines < 400 (ideal < 200)
- [ ] All commits are atomic
- [ ] No "WIP" or "fixup" commits
- [ ] PR title describes the change
- [ ] Description explains why, not just what
Red Flags (Stop and Split)
- ❌ Commit message needs "and"
- ❌ > 10 files in one commit
- ❌ > 400 lines in one commit
- ❌ Mix of features, fixes, and refactors
- ❌ "I'll clean this up later"
Quick Reference
Thresholds
Files: ≤ 5 = 🟢 | 6-10 = 🟡 | > 10 = 🔴Lines: ≤ 200 = 🟢 | 201-400 = 🟡 | > 400 = 🔴Time: ≤ 30min = 🟢 | 30-60min = 🟡 | > 60min = 🔴
Commands
bash
# Quick statusgit diff --shortstat HEAD# Detailed file listgit diff --stat HEAD# Partial staginggit add -p# Check before PRgit diff main --shortstat
Commit Now If
- ✅ Tests just passed
- ✅ > 200 lines changed
- ✅ > 5 files changed
- ✅ About to switch tasks
- ✅ Current state is "working"