| name | git-commit-message |
| description | Rules for git commits - format, staging, visibility gate, workflow. Load on intent to commit, stage, or compose a commit message. Triggers: "commit", "write a commit message", "stage this", "let's ship", "ready to push", conventional commit, selected file `.git/COMMIT_EDITMSG`, wrapping up work, related slash command.
|
Git commit messages
Precedence: repo-level AGENTS.md / CLAUDE.md commit rules override this
skill. Check the repo first; if it forbids conventional commits or mandates a
specific style, follow that and skip the type/scope rules below.
Hard rules
- Never commit without explicit user request. "Done" is not a commit. Wait
for "commit", "ship it", or equivalent.
- Permission to commit is per-action, not autonomous mode. It does not waive
any validation, gate, or skill workflow that would otherwise apply.
- Never include: co-authors, sign-offs, AI attribution, "Generated by
Claude" footers.
git log is a fallback signal when no repo-level rule exists and the workflow
step 1 sample is mixed. Repo rules and this skill win over inferred style.
- FORBIDDEN:
git checkout, git revert, git reset - undoes pre-existing
changes. Track edits manually.
- FORBIDDEN: history rewrites - no
git rebase, commit --amend,
push --force, --force-with-lease. PRs squash-merge; messy branch history
is fine.
Format
Format depends on position in branch.
- First commit of a branch: conventional commit with
type(scope): subject,
optional bullet body.
- All subsequent commits on the branch: one-line subject only, no
type/scope, no body.
First commit (type/scope)
type(scope): subject
- bullet 1
- bullet 2
- bullet 3
Rules:
- Subject: imperative mood, ≤70 chars total (type + scope + parens + colon +
space + subject). Lowercase after the colon.
- Body: bullet list only. No bold, italics, code blocks, or prose
paragraphs.
- Bullets: 3-7 words each. Capture the "why", not minor implementation
details (skip "added validation", "introduced tests", "refactored X").
- Body length: each line ≤72 chars.
- Standard markdown only. No em-dashes, curly quotes, special characters.
- Single-change commit: subject only, no body.
Subsequent commits (one-liner)
- Imperative mood, ≤70 chars.
- FORBIDDEN:
type(scope): prefix. No exceptions. Not fix(ui):, not
docs(adr):, not chore:. Bare imperative subject only.
- No body.
- One change per commit; if scope grows, split into multiple one-liners.
How to detect "first commit of a branch": the branch has no commits ahead of
its base (default branch). Check with git rev-list --count <base>..HEAD - 0
means the next commit is the first. Any other number (1, 2, 6, 50) means the
next commit is a subsequent commit and MUST be a bare one-liner. On
main/master itself, treat every commit as a "first commit" (use type/scope).
Red flags (subsequent commits)
These thoughts mean STOP - you are about to break the rule:
- "The change is meaningful enough to deserve a scope." -> No. One-liner.
- "fix(ui) reads cleaner than the bare subject." -> No. One-liner.
- "Conventional Commits is standard, surely it applies here." -> No. One-liner.
- "Squash-merge will drop it anyway, doesn't matter." -> No. One-liner.
- "Just this one needs a type." -> No. One-liner.
Type
Infer from the diff. If unclear: ask.
Common types: feat, fix, refactor, docs, test, chore, perf,
build, ci, style.
Scope
Priority order:
- User-provided.
- Jira/ticket ID matching
[A-Z]{3}-[0-9]+ from branch name.
- Branch name (excluding
main/master).
- Affected module/folder.
Unavailable: ask.
GitHub references
GitHub renders rich snippets (title + state) for issue/PR references only
inside bullet lists.
Closing/linking keywords (fix, close, resolve, plus
fixes/closes/resolves) only auto-close when placed directly in front
of the id.
Reference forms (all valid in a bullet list):
- Same repo:
#123
- Cross-repo short:
org/repo#123 (preferred for cross-repo)
- Full URL:
https://github.com/org/repo/issues/123 (also unfurls; verbose)
Usage:
- Use
fix for issues the commit resolves: - fix #123, - fix org/repo#123.
- Use
close for PRs the commit supersedes: - close #456.
- Plain reference (no auto-close):
- related #789.
- Cross-repo references must also sit inside a bullet list to render the rich
snippet.
- Never put
#id or org/repo#id references in prose paragraphs - the rich
snippet will not render.
Workflow
-
Discover repo conventions once per session. Skip if already run this
session. If you've already committed on this branch this session, it's a
subsequent commit - skip the check. Re-run only on branch switch or user
request. Single command:
git rev-list --count "$(git symbolic-ref refs/remotes/origin/HEAD \
| sed 's@^refs/remotes/origin/@@')"..HEAD 2>/dev/null \
; git log -3 --pretty=format:'%s'
Fallback if origin/HEAD missing: use main or master.
- Count
0 -> first commit on branch. Use type(scope): subject + optional
bullet body.
- Count > 0 -> subsequent commit. Bare one-liner, no type, no scope, no body.
The forbidden-prefix rule from "Subsequent commits" applies.
- Repo-level rule (AGENTS.md/CLAUDE.md) overrides both.
- Sample subjects mixed and no repo rule: ask user.
- State the count + sampled style in chat before composing. Skipping this
check is the most common failure mode.
-
Determine scope of changes.
- Staged files exist: use those only.
- Nothing staged: ask whether to stage all modified, or to base the message
on the full branch diff vs default branch.
- Selected file is
.git/COMMIT_EDITMSG: use the verbose diff already in
that file; ignore spell/lint issues; write the message to the top of that
file instead of committing.
-
Read the full diff, not just filenames. Understand what was introduced,
modified, removed.
-
Check branch context. If on a feature branch, scan prior commits in the
branch (not on main) to understand the progression and avoid duplicating
intent.
-
Compose message per format above. Re-check: does the format match the
branch position from step 1? Subsequent commit with type(scope): prefix is
a bug, not a stylistic preference.
-
Show, then commit (visibility gate):
- Output the full message as a markdown fenced code in chat, with proper
markdown type for highlights
- Immediately call
git commit with the same message in the same turn. Do
NOT end the turn between message and commit.
- Never commit without showing the message first.
- Never show the message and end the turn without committing (unless the
user invoked a "draft only" path; see below).
-
Pass the message via heredoc on stdin to preserve formatting:
git commit -F- <<'EOF'
type(scope): subject
- bullet 1
- bullet 2
EOF
Draft-only path
When the user wants the message but not the commit (e.g. explicit "just draft
it", "don't commit yet"):
- Output the message as a code block in chat.
- Do NOT call
git commit.
- If the selected file is
.git/COMMIT_EDITMSG, apply the message to the top of
that file instead.
The visibility gate (step 6) does not apply on this path.
Why these rules
- Bullets over prose: matches user's terse style; scannable in GitHub UI;
forces "why" over "what".
- Show + commit in same turn: the alternative (show, wait, commit next turn)
doubles round-trips on every commit. User prefers to review the diff and
message together, then approve the whole turn at once.
- Heredoc on stdin (
-F-): shell-escaping multiline messages with
-m "..." drops newlines or breaks on quotes. Stdin sidesteps shell argument
quoting entirely.
git log as fallback only: history may be inconsistent or contain old
conventions. Repo-level rules and this skill win; git log resolves ambiguity
when neither applies.