Contenuto dal repository con titoli, esempi, codice, tabelle, link e immagini preservati.
Commit Message
Draft a high-quality commit message for the staged changes and create the commit.
Inputs you must gather first
Run these before drafting anything. Skipping them produces guesses, not messages.
git rev-parse --is-inside-work-tree
git status --short
git diff --staged --stat
git diff --staged
git log -n 20 --onelineUse the recent log to learn the repository's own conventions (type vocabulary, scope style, casing) and follow them when they don't conflict with the rules below. If the log shows a clearly different style, prefer the repo's style and mention the deviation to the user once.
Staging behavior depends on what is already staged:
- Nothing staged: you may
git addthe relevant changes yourself so the commit has content. Pick the files that form one focused change. - Something already staged: the user has signalled what they want in this commit. Before adding anything else, ask whether the other unstaged files should be included too — do not silently expand the staged set.
Output format
Produce a Conventional Commits 1.0.0 message:
<type>(<scope>): <subject>
<body explaining why>
<optional footer(s)>Subject line
- Use one of the standard types:
feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert. Pick the one that best matches the user-visible effect, not the largest file touched. featandfixmap to MINOR and PATCH in SemVer. Reserve them for behavioral changes; userefactor,chore,docs,test, etc. when behavior is unchanged.- Scope is optional. Include it when there is an obvious, stable module/package/area (e.g.
auth,parser,ci). Omit it rather than invent one. - Breaking changes: append
!after the type/scope (e.g.feat(api)!: ...) AND add aBREAKING CHANGE:footer describing the break. - Description: imperative mood, lowercase first letter (unless the repo log clearly uses Sentence case), no trailing period, target ≤ 50 characters and never exceed 72.
- Write in English unless the user has explicitly asked for another language.
Body — optional, and short when present
Default to subject-only. If the subject alone conveys the change and its intent, omit the body entirely — most commits land here. Add a body only when there is genuinely non-obvious rationale a future reader would otherwise miss.
The diff already shows what changed line-by-line; re-narrating it adds nothing. When a body is warranted, write only the point that actually applies — do not pad to fill all three:
- What problem or need motivated this change (when not obvious from the subject)?
- Why this approach over a plausible alternative (only when the choice is non-obvious)?
- A constraint, tradeoff, or non-obvious consequence worth flagging.
Scope of the body: pick the single most valuable point and state it. If you find yourself writing more, the surplus is almost always re-narrated diff — cut it. When in doubt, omit the body rather than pad it. Footers are separate — a BREAKING CHANGE: description may run as long as the break requires.
Wrap body lines at 72 characters. Separate subject and body with a blank line.
Anti-patterns to refuse:
- "Update foo.py" / "Various changes" / "WIP" — these communicate nothing.
- A bullet list that paraphrases the diff ("Added X. Removed Y. Renamed Z."). If a reader wants that, they can read the diff. State the reason those changes were made together.
- Marketing language ("improve", "enhance", "better") without saying what made it worse before or what concretely improves.
Footers
Use footers for machine-readable metadata, one per line:
BREAKING CHANGE: <description>— mandatory for any breaking change.Refs: #123,Closes: #123,Fixes: #123— issue tracker references when the user provides them or they appear in branch names.Co-authored-by: Name <email>— when applicable.
Do not invent issue numbers. If unsure, leave footers off.
Atomicity check — do this BEFORE drafting
A good commit captures one focused, logically coherent change. Before writing the message, scan the staged diff for signs the staging area mixes unrelated concerns:
- Multiple unrelated
feat/fixcandidates in different modules. - A refactor bundled with a behavior change (these should almost always be separate commits — the refactor commit becomes reviewable, and the behavior commit becomes bisectable).
- Formatting / whitespace churn mixed with substantive edits.
- An unrelated dependency bump alongside feature work.
If you spot any of these, stop and surface the issue to the user before drafting. Your job here is to inform, not to block — name the distinct changes you see, propose a concrete split (which hunks/files belong to which commit) with the exact commands to perform it, then ask whether they want to split or to proceed with a single commit anyway. If they choose to proceed, draft the message normally and note the mixing in the body in one short sentence, so the history is honest about it. Example 4 below shows the shape of that response.
See references/atomicity.md for splitting recipes.
Drafting workflow
The default mode is end-to-end: draft the message and commit, in a single response, without waiting for the user to approve the draft. The user invoked /atomicity-commit because they want a commit, not a draft for review. Treat the message as final and run git commit.
- Read the inputs listed above.
- Run the atomicity check. If mixed: stop and follow that section — do not commit anything in this turn. If clean: continue without asking.
- Classify the change (type, scope, breaking?).
- Write the subject — imperative, ≤ 50 chars target, ≤ 72 hard limit.
- Decide on the body per Body above: default to subject-only.
- Add footers only if warranted (BREAKING CHANGE, issue refs the user mentioned, etc.).
- Commit immediately with
git commit -m "<subject>" -m "<body>"— each-mbecomes its own paragraph, so a third-mcarries a footer. That covers any message within the length budget; seereferences/committing.mdfor the-Ffallback when quoting gets awkward. - After the commit, run
git --no-pager log -1 --format=fullerand show the user what was recorded, so they can verify and--amendif needed. - Do not add
Co-authored-by: Claudeor any Anthropic/Claude attribution unless the user asks for it.
When NOT to auto-commit even on a clean stage:
- A pre-commit hook fails. Surface the hook's output verbatim and stop. The user decides whether to fix it, retry with
--no-verify, or abandon. - The user's prompt explicitly asks for a draft only ("just draft the message", "show me what you'd write", "don't commit yet"). Honor that — show the message and stop.
- The repository is in a detached HEAD, in the middle of a rebase/merge, or otherwise in a state where committing would be surprising. Mention the state and ask before proceeding.
Examples
Example 1 — feature with rationale
Staged diff: adds a retry wrapper around the S3 upload call with exponential backoff.
feat(uploader): retry S3 uploads with exponential backoff
Transient 503s from S3 were failing ~2% of CI runs. The 5-attempt cap
keeps a genuine outage failing the build within a minute.Why this is good: the subject states the change in imperative mood. The body never re-describes the diff — it gives the failure mode that motivated the change plus the one non-obvious consequence of the design, in two lines.
Example 2 — bug fix with breaking semantics
Staged diff: changes the public parse() function to throw on empty input instead of returning null.
fix(parser)!: throw on empty input instead of returning null
Three production crashes last quarter traced back to a caller that
forgot the null-check the old contract required.
BREAKING CHANGE: parse("") previously returned null; it now throws
EmptyInputError. Callers relying on the null return must catch the
error or pre-check for empty strings.Why this is good: the ! marker and BREAKING CHANGE footer are both present (the spec requires the footer; the ! is a visual aid). The body cites concrete evidence rather than abstract "improvements" and stays within budget; the footer sits outside that budget and runs as long as the break needs.
Example 3 — chore where no body is needed
chore: bump prettier to 3.3.3Why this is good: the subject is self-explanatory; padding it with a body would be noise. This is the common case, not the exception.
Example 4 — refusing a mixed commit
The user has staged a refactor of the auth module and a fix to a pagination bug in the search module. Do not draft a single message. Respond with something like:
The staged changes look like two separate things: an auth-module rename and a search-pagination off-by-one. Splitting them gives you a clean revert path for either one. Suggested split: - Commit 1 (refactor):src/auth/*- Commit 2 (fix):src/search/pagination.ts,src/search/pagination.test.tsTo do this: ``git restore --staged src/search/pagination.ts src/search/pagination.test.ts # commit the auth refactor first, then re-stage and commit the fix`` Want me to proceed with the auth commit, or would you rather stage things differently?
When the user pushes back
- "Just write it in one commit" → do it, with the one-sentence acknowledgement of the mixing described in the atomicity section.
- "Make the message shorter" → tighten the body; never sacrifice the why. If the subject is at 50 chars, that's fine.
- "Write it in Japanese" (or another language) → switch the message to that language; keep the Conventional Commits prefix (
feat:,fix:, …) in English since it's a structural marker.
Reference files
references/atomicity.md— splitting recipes (partial staging, undoing mixed stages).references/committing.md— the-Ffallback, verifying the commit, hook failures.
