commit-message
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.
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
gitea-workflow
IncludedOrchestrate agile development workflows for Gitea repositories using the tea CLI. Use when working with Gitea-hosted repos and asking to 'run the workflow', 'continue working', 'what's next', 'complete the task cycle', 'start my day', 'end the sprint', 'implement the next task', or wanting guided step-by-step development assistance. Keywords: workflow, orchestrate, agile, task cycle, sprint, daily, implement, review, PR, standup, retrospective, gitea, tea.
microsoft-graph-gateway
IncludedRoute Microsoft Graph work in this workspace. Use when users want to read or write Outlook mail, calendar events, contacts, OneDrive or SharePoint files, Teams, Planner, To Do, users, groups, directory data, or arbitrary Microsoft Graph endpoints from VS Code. Prefer WorkIQ for common read scenarios. Use Microsoft Graph for write actions and gap-read scenarios that need exact Graph properties, filters, permissions, or endpoints.
copilotkit
IncludedUse when building with CopilotKit — setup, development, integrations, debugging, upgrading, or contributing. Routes to the appropriate specialized skill based on the task.
wordly-wisdom
IncludedProvides calibrated decision analysis using Charlie Munger-style multiple mental models, inversion, incentive mapping, circle-of-competence checks, misjudgment audits, second-order effects, and forecast updates. Use when the user asks for an oracle take, a hard call, a decision memo, a premortem, an outside view, a red-team, a sanity-check, what am I missing, think this through, or wants a strategy, hire, investment, plan, product, partnership, or major life choice analysed. Avoid for simple factual lookups or time-sensitive legal, medical, or market questions without fresh evidence.
swain-session
IncludedSession management and project status dashboard. Owns the full session lifecycle (start/work/close/resume), focus lane, bookmarks, worktree detection, and tab naming. Also serves as the project status dashboard — shows active epics, progress, actionable next steps, blocked items, tasks, GitHub issues, and recommendations. Worktree creation is deferred to swain-do task dispatch (SPEC-195). Triggers on: 'session', 'status', 'what's next', 'dashboard', 'overview', 'where are we', 'what should I work on', 'show me priorities', 'bookmark', 'focus on', 'session info'.
gandi
IncludedComprehensive Gandi domain registrar integration for domain and DNS management. Register and manage domains, create/update/delete DNS records (A, AAAA, CNAME, MX, TXT, SRV, and more), configure email forwarding and aliases, check SSL certificate status, create DNS snapshots for safe rollback, bulk update zone files, and monitor domain expiration. Supports multi-domain management, zone file import/export, and automated DNS backups. Includes both read-only and destructive operations with safety controls.