Conventional Commits
Default commit format: Conventional Commits. Use this format for all commits and PR/MR titles unless the project defines its own commit conventions (in CLAUDE.md, AGENTS.md, contributing guides, or similar). Project-specific rules always take priority.
When to Use
- Making any git commit -- this skill defines the required format
- Creating PR/MR titles -- squash merges use the title as the commit message
- Writing squash merge messages -- must follow the same format
- Reviewing commit message format -- validate against these rules
Critical Rules
- Project rules override this skill -- if the project defines commit message conventions (issue number prefixes, custom formats, etc.), follow those instead. This skill is the default when no project-specific rules exist.
- Type is required -- never commit without a type prefix
- Description is lowercase, imperative mood, no period:
fix: handle null response not Fix: Handled null response.
- No
Co-Authored-By trailer -- never add it to commit messages
- Describe the change, not the process -- never write review provenance (
fix: coderabbit round 2 fixes, fix: address review feedback) as the message; state what the commit changes. The trigger for the change already lives in the PR and its threads.
- No filler -- the description alone is usually the whole message; add a body only for information the description and diff cannot carry (breaking change details, migration steps, non-obvious constraints). Never narrate the diff.
Provider Detection
Detect the git provider to use the correct CLI:
git remote get-url origin
| Remote URL contains |
Provider |
CLI |
PR term |
github.com |
GitHub |
gh |
PR |
gitlab.com or self-hosted GitLab |
GitLab |
glab |
MR |
If ambiguous or both present, ask the user.
Format
<type>(<optional scope>): <description>
[optional body]
[optional footer(s)]
Types
| Type |
When |
feat |
New feature or capability |
fix |
Bug fix |
docs |
Documentation only |
style |
Formatting, whitespace, semicolons (no logic change) |
refactor |
Code change that neither fixes a bug nor adds a feature |
perf |
Performance improvement |
test |
Adding or updating tests |
build |
Build system or external dependencies |
ci |
CI/CD configuration |
chore |
Maintenance tasks, tooling, config |
Rules
- Type is required -- never commit without a type prefix
- Scope is optional but encouraged for multi-module repos:
feat(auth): add OAuth2 flow
- Description is lowercase, imperative mood, no period:
fix: handle null response not Fix: Handled null response.
- Breaking changes use
! after type/scope: feat(api)!: remove v1 endpoints
- PR/MR titles follow the same format -- squash merges use the PR/MR title as the commit message
- No
Co-Authored-By trailer -- never add it to commit messages
- Describe the change, not the process -- state what changed, never why a reviewer asked for it (see Review-Fix Commits below)
- Body is optional and rare -- add one only for what the description and diff cannot carry; never restate the diff or pad with narrative
Commit Examples
git commit -m "feat: add user profile page"
git commit -m "fix(auth): prevent token refresh race condition"
git commit -m "docs: update API reference for v2 endpoints"
git commit -m "refactor(db): extract connection pooling logic"
git commit -m "feat(api)!: change response format for /users"
Review-Fix Commits
Commits that address review feedback (human or bot) follow the same rule as any other commit: the message states what changed. The trigger -- reviewer, bot, round number -- is process context that already lives in the PR threads and is noise in git log.
| Noise (never) |
Signal |
fix: coderabbit round 2 fixes |
fix: guard nil user in session refresh |
fix: address PR review feedback |
fix: close file handle on early return |
chore: apply copilot suggestions |
refactor: dedupe retry logic across fetchers |
One review round can produce commits of different types -- split by change, not by round.
PR/MR Title Examples
| Provider |
Create PR/MR with title |
| GitHub |
gh pr create --title "feat: add dark mode" --body "..." |
| GitLab |
glab mr create --title "feat: add dark mode" --description "..." |
1---2name: git-commit3description: Conventional Commits format for git commits and PR/MR titles. Type prefixes, scope rules, breaking change syntax, and commit message structure. Use when committing changes, writing commit messages, creating PR/MR titles, or formatting squash merge messages. Not for PR workflows (git-pr), CI/CD status (git-ci), or git branch management4---56# Conventional Commits78**Default commit format: [Conventional Commits](https://www.conventionalcommits.org/).** Use this format for all commits and PR/MR titles unless the project defines its own commit conventions (in CLAUDE.md, AGENTS.md, contributing guides, or similar). Project-specific rules always take priority.910## When to Use1112- **Making any git commit** -- this skill defines the required format13- **Creating PR/MR titles** -- squash merges use the title as the commit message14- **Writing squash merge messages** -- must follow the same format15- **Reviewing commit message format** -- validate against these rules1617## Critical Rules18191. **Project rules override this skill** -- if the project defines commit message conventions (issue number prefixes, custom formats, etc.), follow those instead. This skill is the default when no project-specific rules exist.202. **Type is required** -- never commit without a type prefix213. **Description is lowercase**, imperative mood, no period: `fix: handle null response` not `Fix: Handled null response.`224. **No `Co-Authored-By` trailer** -- never add it to commit messages235. **Describe the change, not the process** -- never write review provenance (`fix: coderabbit round 2 fixes`, `fix: address review feedback`) as the message; state what the commit changes. The trigger for the change already lives in the PR and its threads.246. **No filler** -- the description alone is usually the whole message; add a body only for information the description and diff cannot carry (breaking change details, migration steps, non-obvious constraints). Never narrate the diff.2526---2728## Provider Detection2930Detect the git provider to use the correct CLI:3132```bash33git remote get-url origin34```3536| Remote URL contains | Provider | CLI | PR term |37|------------------------------------|----------|--------|---------|38| `github.com` | GitHub | `gh` | PR |39| `gitlab.com` or self-hosted GitLab | GitLab | `glab` | MR |4041If ambiguous or both present, ask the user.4243---4445## Format4647```text48<type>(<optional scope>): <description>4950[optional body]5152[optional footer(s)]53```5455## Types5657| Type | When |58|------------|---------------------------------------------------------|59| `feat` | New feature or capability |60| `fix` | Bug fix |61| `docs` | Documentation only |62| `style` | Formatting, whitespace, semicolons (no logic change) |63| `refactor` | Code change that neither fixes a bug nor adds a feature |64| `perf` | Performance improvement |65| `test` | Adding or updating tests |66| `build` | Build system or external dependencies |67| `ci` | CI/CD configuration |68| `chore` | Maintenance tasks, tooling, config |6970## Rules71721. **Type is required** -- never commit without a type prefix732. **Scope is optional** but encouraged for multi-module repos: `feat(auth): add OAuth2 flow`743. **Description is lowercase**, imperative mood, no period: `fix: handle null response` not `Fix: Handled null response.`754. **Breaking changes** use `!` after type/scope: `feat(api)!: remove v1 endpoints`765. **PR/MR titles follow the same format** -- squash merges use the PR/MR title as the commit message776. **No `Co-Authored-By` trailer** -- never add it to commit messages787. **Describe the change, not the process** -- state what changed, never why a reviewer asked for it (see Review-Fix Commits below)798. **Body is optional and rare** -- add one only for what the description and diff cannot carry; never restate the diff or pad with narrative8081## Commit Examples8283```bash84git commit -m "feat: add user profile page"85git commit -m "fix(auth): prevent token refresh race condition"86git commit -m "docs: update API reference for v2 endpoints"87git commit -m "refactor(db): extract connection pooling logic"88git commit -m "feat(api)!: change response format for /users"89```9091## Review-Fix Commits9293Commits that address review feedback (human or bot) follow the same rule as any other commit: the message states what changed. The trigger -- reviewer, bot, round number -- is process context that already lives in the PR threads and is noise in `git log`.9495| Noise (never) | Signal |96|-----------------------------------|-----------------------------------------------|97| `fix: coderabbit round 2 fixes` | `fix: guard nil user in session refresh` |98| `fix: address PR review feedback` | `fix: close file handle on early return` |99| `chore: apply copilot suggestions`| `refactor: dedupe retry logic across fetchers`|100101One review round can produce commits of different types -- split by change, not by round.102103## PR/MR Title Examples104105| Provider | Create PR/MR with title |106|----------|----------------------------------------------------------------------|107| GitHub | `gh pr create --title "feat: add dark mode" --body "..."` |108| GitLab | `glab mr create --title "feat: add dark mode" --description "..."` |