commit-message
Write commit messages from evidence (the diff), not from recollection.
Procedure
- Run
git status --porcelainandgit diff --cached --stat. If nothing is staged, ask whether to stage all tracked changes (git add -u) or specific paths. Nevergit add -Asilently (untracked junk, secrets). - Read the staged diff:
git diff --cached. If it exceeds ~400 lines, read--statplus the hunks of the 5 largest files. - Classify the change:
feat,fix,refactor,perf,docs,test,build,ci,chore. Pick ONE. If the diff mixes types, say so and offer to split into two commits. - Scope = the top-level directory or module most touched (
auth,api,cli). Omit when the change is cross-cutting. - Subject: imperative, ≤ 50 chars, no trailing period.
fix(auth): reject expired refresh tokens. - Body only when the why is not obvious from the diff: 1 to 3 lines, wrap at 72. Reference issues as
Refs #123/Closes #123on their own line. - Show the message, then commit with a heredoc so newlines survive:
git commit -m "$(cat <<'MSG' fix(auth): reject expired refresh tokens Tokens past `exp` were accepted because the check used `<` instead of `<=`. Closes #412 MSG )" - Print
git log -1 --statas proof.
Rules
- Never describe changes that are not in the staged diff.
- Never include secrets, tokens, or internal URLs in the message.
- Do not add "Co-Authored-By" or tool attribution unless the repo's CONTRIBUTING or the user asks for it.
- If tests were not run, do not claim they pass in the message.
Eval
evals/commit-message/: fixture repo with a staged two-file bug fix; expected: fix(...) subject ≤ 50 chars, body mentions the off-by-one, no unrelated files described.