| name | commit-writing |
| description | Write git commit messages that follow Conventional Commits. Keep them lean: the subject line states the intent in one line; add a body only when the diff can't speak for itself. Use when creating git commits, writing commit messages, splitting a working tree into commits, or when the user mentions "写 commit", "commit message", "提交信息", "提交规范". |
Commit Writing
Write the intent the diff cannot show; never restate the diff. The readers are people tracing "why was this line changed" through git log / git blame, and tooling that derives changelogs and semver bumps from the type.
Format
Follow Conventional Commits; types, !, and BREAKING CHANGE work as the spec says and are not repeated here. Conventions beyond the spec:
- Always English, even on Chinese-speaking teams (types are English-based; CI and changelog tooling expects it)
- Prefer a scope: the affected module / package (package name in a monorepo); skip it when the change spans unrelated modules — don't force one
Subject
- Imperative verb first (
add, not added), lowercase, no trailing period, ≤ 70 chars including type / scope
- Say what changed; leave the why to the body. Must stand on its own in
git log --oneline
- Bad:
fixed bug / update auth / WIP / restating the diff / emoji / adjectives ("major improvement") / tooling metadata ("AI-assisted")
- Good:
fix(auth): race condition in token refresh under concurrent login, refactor(db): extract connection pool from request middleware
Body
Most commits need no body. Add one only when the diff can't show it (blank line after the subject, wrap at 72 chars):
- Why not the more obvious alternative
- The exact trigger of the bug (race / specific input / permission boundary)
- Issue references (
Refs: #123, Fixes: SEC-431) and hard numbers (reduces p95 from 800ms to 120ms)
A body longer than the diff means it is restating code — cut everything the diff proves by itself.
Split or squash
Each commit is a unit that can be reviewed and reverted independently:
- Multiple unrelated concerns (refactor + feature + bugfix) → split with
git add -p (git reset HEAD~ first if already mixed)
- A chain of small steps serving one intent (rename + update imports + fix types) → squash
- Never cut at a state that breaks CI or compilation