Git Commit Message
Produce evidence-based commit messages that follow Conventional Commits 1.0.0. Treat every message as a recommendation: inspect changes without modifying the repository, and never run git add, git commit, or another command that changes Git state.
Gather the Change Evidence
- Read applicable repository instructions and explicit commit policies.
- Use a user-provided diff, patch, file list, or change summary when that is the requested source.
- Otherwise, verify that the current directory is in a Git worktree and inspect all uncommitted changes:
- Run
git status --short. - Read both
git diff --cachedandgit diff, including their--statsummaries when the patch is large. - List untracked paths with
git ls-files --others --exclude-standard, then inspect relevant text files. Skip binary, generated, vendored, secret-bearing, or excessively large files and disclose any skipped context that could affect the result.
- Run
- Inspect recent commit subjects only when useful for established scope names or trailer style. Do not copy malformed history or change the default message language from English unless an explicit repository policy or the user requires it.
- If there are no changes and no usable user-provided description, state that there is not enough change evidence to generate a commit message.
Base the message on the observed behavior and intent of the whole change. Do not infer issue numbers, breaking behavior, migration requirements, or business intent from filenames alone.
Cover the Whole Change Set
Produce one commit message that covers the entire inspected change set, or the entire user-provided source. Do not volunteer a split into several commits: the user has to reproduce any split by hand, and a partially staged working tree is hard to undo.
Treat tests, documentation, and configuration that support the same work as part of that single message. When the change set mixes intents, such as a feature plus an unrelated fix, or refactoring plus behavior changes:
- Take the type, scope, and description from the primary intent.
- Summarize the secondary intents in the body as short bullets when a reviewer needs them to understand the full change.
- Prefer a broader description over a narrow one that hides part of the change.
Split the change set into several messages only when the user explicitly asks for a split.
Choose the Type
Choose the type from the primary intent, not merely from the files changed:
| Type | Use for |
|---|---|
feat |
Add a new user-facing or developer-facing capability |
fix |
Correct incorrect behavior or a defect |
perf |
Improve performance without changing intended behavior |
refactor |
Restructure code without adding a feature or fixing a defect |
docs |
Change documentation or comments only |
style |
Change formatting or style without affecting behavior |
test |
Add or change tests without a corresponding production change |
build |
Change dependencies, packaging, or the build system |
ci |
Change continuous-integration or delivery configuration |
chore |
Perform maintenance not covered by another type |
revert |
Revert one or more earlier commits |
Prefer the most specific supported type. Use chore only as a fallback.
Compose the Message
Use this structure:
<type>[optional scope][optional !]: <description>
[optional body]
[optional footer(s)]
Apply these rules:
- Use a lowercase type.
- Add a short noun scope in parentheses only when one coherent codebase area is clear, such as
api,auth, orparser. Omit the scope when it would be guessed, overly broad, or misleading. - Write the description in concise imperative English. Start with a lowercase verb, describe the resulting change, and omit the final period.
- Keep a simple change to the header alone.
- Add a body only when it materially explains motivation, important behavior, secondary intents in a mixed change set, or a non-obvious before/after distinction. Separate it from the header with one blank line and do not repeat the header.
- Add footers only when supported by the change evidence or user-provided context. Use Git-trailer-compatible forms such as
Refs: #123orCloses #123. - Mark a breaking change with
!immediately before the colon. Add aBREAKING CHANGE: <description>footer when migration impact or replacement behavior needs explanation. Never label an internal refactor as breaking without evidence of an incompatible public contract.
Example of a simple message:
fix(parser): prevent duplicate option parsing
Example with a body and footers:
feat(api)!: require scoped access tokens
Reject legacy unscoped tokens during authentication.
BREAKING CHANGE: Existing clients must request a scoped token.
Refs: #123
Example of a mixed change set covered by one message:
feat(auth): add password reset flow
- correct expired-token handling in the session middleware
- document the new endpoint in the API reference
Return the Result
Return exactly one fenced text block containing the final commit message, with no preamble or explanation.
Return several blocks only on explicit request: numbered groups with one block each when the user asks for a split, or one block per variant when the user asks for alternative wordings. Keep supporting prose minimal.
When revising or validating an existing message, preserve its supported intent, correct any structural or wording problems, and return the corrected message in the same output format. Ask one concise question only when missing context would materially change the type, breaking-change marker, or footer; otherwise produce the best evidence-based result.
The message rules are based on Conventional Commits 1.0.0 and the practical type and wording guidance in Git 提交规范指南.