Claude
Skills
Sign in
Back

commit-message

Included with Lifetime
$97 forever

Git commit message conventions: structure, formatting, scoping, body content, breaking changes, trailers. Invoke whenever task involves any interaction with commit messages — writing, reviewing, validating, or understanding message format.

Productivity

What this skill does


# Commit Message Format

<scope>
These rules apply **only to git commit messages**. Do not apply line length limits, formatting
conventions, or structure requirements from this skill to other files (code, documentation, configs, etc.).
</scope>

A good commit message is a patch note read by colleagues, QA, and future you.

<mental-model>
Before writing, imagine:
- You're writing a patch note for users
- You're writing a task for QA to verify
- Someone will read this at 3am debugging production
</mental-model>

## What Makes a Good Message

<context-principle>
The best commit messages draw from three sources:

- **The task** — what problem was being solved
- **The implementation context** — why this approach was chosen
- **The deliverable** — what was actually built

When all three are available, use them. The code shows WHAT exists; context reveals WHY. When context is incomplete,
describe what you can verify from the code and available information. </context-principle>

### Factual, Not Promotional

<factual-principle>
Commit messages are **factual records**, not marketing copy.

**Subject line**: Strictly factual. Imperative mood. No judgment. Describes what was done, not how good it is.

**Body**: Can explain reasoning and trade-offs, but remains objective. Avoid promotional language.

The subject answers: "What did this commit do?" Not: "Why is this commit amazing?" </factual-principle>

## Structure

<format>
```
[scope] subject

body

trailers

```

**Subject**: What changed (≤50 chars target, 72 hard cap, factual)
**Body**: Why it changed, how to verify
**Trailers**: Structured metadata (references, authorship)
</format>

### ASCII Symbols

<charset>
Stick to ASCII punctuation and symbols. Non-English prose is fine — the restriction is on decorative/typographic
Unicode, not natural language.

- No em/en dashes (—, –) — use `--` or `-`
- No arrows (→, ←, ↔) — use `->`, `<-`, `<->`
- No bullet symbols (•, ▸) — use `-` or `*`
- No fancy quotes (“”, ‘’) — use straight quotes
- No emoji (🐛, ✅, 🚀) — unless project convention requires it
- No other decorative symbols (©, ™, §, ¶, ∞)

Git tooling, terminals, email patches, and `git log` render ASCII reliably everywhere. Unicode symbols break in some
environments and add no information over their ASCII equivalents.
</charset>

## Subject Line

```

[scope] <verb> <description> # with scope (monorepos)

<verb> <description>            # without scope (single-purpose repos)
```

<subject-rules>
- Soft target 50 chars; hard cap 72
- Imperative mood: "add" not "added"
- Lowercase after scope (except proper nouns)
- No period at end
- **Factual**: describe what, not how good
- **No filler tics**: drop "this commit", "I", "we", "now", "currently"; never restate the scope's filename
</subject-rules>

### Scope (Optional)

Scope is useful for **monorepos** or repositories with multiple deliverables. For single-purpose repositories, scope can
be omitted.

<scope-guidance>
**Use scope when:**
- Monorepo with multiple projects/packages
- Repository contains distinct subsystems (frontend, backend, libs)
- Changes need to be filtered by component in git log

**Omit scope when:**

- Repository has a single purpose
- All code serves one deliverable
- Scope would always be the same </scope-guidance>

When using scope, it identifies the affected subsystem:

```
[parser]          # top-level project
[core/auth]       # nested path
[web/api]         # component within project
[myapp/backend]   # or abbreviated: [myapp/b]
```

Determine scope from file paths (not contents) — use the common parent directory or the most significant component
affected.

## Body

<body-philosophy>
A good commit message is rarely single-line.

The body is where you communicate with future readers. It answers:

- **What** changed beyond the subject
- **Why** this change was needed
- **How to verify** if not obvious

Wrap all body lines at 72 characters. This is a hard limit, not a guideline — git tooling (log, format-patch, email)
assumes 72-char body lines. Trailers are the only exception. </body-philosophy>

### When Body is Essential

- Bug fix — explain WHY the bug existed, not just what you fixed
- Feature — explain the use case
- Refactoring — explain the motivation
- Breaking change — explain migration path
- Non-obvious change — explain rationale
- Part of a commit chain — state what related work follows

### Terse Register

The diff carries the _what_; the message carries the _why_. Subjects and bodies are records, not narratives. Bodies may
use fragments and drop articles where clarity survives. Identifiers, file paths, and error strings stay exact.

**Never include:**

- "This commit does X", "This change..." — the diff says what.
- "I", "we" — the commit speaks for itself.
- "now", "currently", "previously" — git history is the timeline.
- "As requested by..." — use a `Co-Authored-By:` trailer or omit.
- Restating the scope's filename: `[parser] update parser code` → `[parser] handle empty input`.
- Promotional adjectives without specifics: "great", "amazing", "improved", "better" — say what is better.
- Decorative Unicode — em dashes, arrows, fancy quotes, emoji, bullet symbols (see ASCII Symbols above).
- Filler: "just", "really", "basically", "actually", "simply"; connective fluff: "however", "furthermore",
  "additionally".

**Bad:**

```
[parser] fix the bug in parser

This commit fixes a bug we found where the parser was incorrectly handling empty input.
I noticed that it would now sometimes panic, so I added a guard to prevent this issue.
```

**Good:**

```
[parser] handle empty input in token scanner

Empty input dereferenced nil in the scanner loop. Returns empty token list instead.

Fixes: #234
```

Subject drops "the bug in parser" (restates scope), states the fix. Body drops "this commit / I / we / now", uses
fragments, names the actual cause.

### Body Patterns

<body-patterns>
**Bug fix — explain the cause:**
```
Session cache was returning nil when the key existed but the value had expired.
The TTL check happened after the nil check, causing panics on expired sessions.

Now returns ErrExpired, allowing callers to distinguish between "not found" and "expired".

```

**Feature — explain the purpose:**
```

Reduces request volume to the API by buffering push attempts and sending them as a single batch request on a configured
interval.

```

**Refactoring — explain the benefit:**
```

- Use Dependency by-pointer to simplify usage patterns
- Add convenience methods: BorrowByName, BorrowByID

Preparation for the new package resolution algorithm.

```

**Commit chain — state what follows:**
```

Integration with the order processing pipeline follows in a separate change.

```

Name the specific work that follows. Not "more changes coming" — say what and where.
</body-patterns>

## Breaking Changes

<breaking-changes>
When a commit breaks backward compatibility, the body MUST start with a `BREAKING:` declaration
as the first paragraph:

```

BREAKING: <what is broken>

<explanation and migration path>
```

The `BREAKING:` prefix is uppercase and followed by a brief description of what breaks. The following paragraphs explain
why and how to migrate. </breaking-changes>

## Trailers (Footer Metadata)

Trailers are structured key-value pairs at the end of the commit message, following
[git-trailer format](https://git-scm.com/docs/git-interpret-trailers).

<trailers>
```
Key-Name: value
Another-Key: value with spaces
```

Blank line separates body from trailers. Each trailer on its own line. All trailers use Title-Case for consistency with
git standards.

</trailers>

### Common Trailers

- `Task:` — link to issue tracker — `Task: https://tracker.example.com/PROJ-123`
- `Fixes:` — issue this commit fixes — `Fixes: #456` or `Fixes: PROJ-456`
- `Refs:` — related issues/commits — `Refs: #123, #124`
- `Closes:` — auto-close issue on merge — `Closes: #789`
- `See:` — related documentation — `See: docs/auth.md`
- `Reviewed-By:` —

Related in Productivity