Conventional Commit
Commit Message Structure
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
Types
| Type |
When to use |
feat |
A new feature |
fix |
A bug fix |
docs |
Documentation changes, no code |
style |
Formatting, missing semicolons, etc. (no logic change) |
refactor |
Code change that is neither a fix nor a feature |
perf |
Performance improvement |
test |
Adding or correcting tests |
ci |
CI configuration changes |
chore |
Maintenance tasks (updating deps, tooling, etc.) |
revert |
Reverts a previous commit |
Append ! after the type/scope to signal a breaking change: feat!: or feat(api)!:
When a change breaks existing behavior, both markers are mandatory: the ! suffix on the type
and the BREAKING CHANGE: footer. They always appear together — never one without the other.
Scope
Optional. Use the name of the area affected, e.g., segment, cache, config, ui.
Omit when the change is truly cross-cutting.
Description
- Required. One short imperative sentence, no period at the end. The full header line (type +
scope + description) must be 72 characters or fewer. Aim for 50 characters or fewer for
the description itself — this almost always keeps the full header within budget regardless
of type and scope length.
- Use the imperative mood: "add", not "added" or "adds". Never past tense or present-third-person:
✗
added, fixed, bumped, implemented → ✓ add, fix, bump, implement.
- Never mirror the input's phrasing. If the request uses past-tense words (
updated, added,
bumped, was removed, got regenerated), convert them to imperative before writing the
description: update, add, bump, remove, regenerate.
Body
Optional. Add context about why the change was made, not what. The diff shows that.
Wrap at 72 characters.
Footer
Use for:
BREAKING CHANGE: <description> (required when ! is used; explains the break).
- Issue references:
Closes #123, Fixes #456.
- Co-authors:
Co-Authored-By: Name <email>.
Workflow
- Run
git status to review changed files.
- Run
git diff and git diff --cached to inspect staged and unstaged changes.
- Identify the type from the table above. Ask yourself: does this change remove, rename, or
alter existing behavior that callers depend on? If yes → it is a breaking change: use
!
after the type/scope and add a BREAKING CHANGE: footer. Both markers are always required
together.
- Identify the scope from the files/area changed.
- Write a short description in the imperative mood.
- Add a body if the why needs explanation.
- Add a footer for breaking changes or issue references.
- Stage the relevant files explicitly (avoid
git add -A).
- Commit with a message that preserves multi-line formatting when body/footer are present.
Examples
feat(segment): add Ramadan segment with Aladhan API
fix(cache): always store mod time
docs(readme): update installation instructions
refactor(config): simplify option parsing logic
chore(deps): bump github.com/shirou/gopsutil/v4
feat(segment)!: rename template property StartTime to Start
BREAKING CHANGE: template strings using .StartTime must be updated to .Start
Validation Checklist
1---2name: conventional-commit3description: Workflow for generating conventional commit messages following the Conventional Commits specification. MUST be invoked every time a commit is created. Guides construction of standardized commit messages with correct type, scope, description, body, and footer.4---56# Conventional Commit78## Commit Message Structure910```text11<type>(<scope>): <description>1213[optional body]1415[optional footer(s)]16```1718### Types1920| Type | When to use |21| ---------- | ------------------------------------------------------ |22| `feat` | A new feature |23| `fix` | A bug fix |24| `docs` | Documentation changes, no code |25| `style` | Formatting, missing semicolons, etc. (no logic change) |26| `refactor` | Code change that is neither a fix nor a feature |27| `perf` | Performance improvement |28| `test` | Adding or correcting tests |29| `ci` | CI configuration changes |30| `chore` | Maintenance tasks (updating deps, tooling, etc.) |31| `revert` | Reverts a previous commit |3233Append `!` after the type/scope to signal a **breaking change**: `feat!:` or `feat(api)!:`34When a change breaks existing behavior, **both markers are mandatory**: the `!` suffix on the type35**and** the `BREAKING CHANGE:` footer. They always appear together — never one without the other.3637### Scope3839Optional. Use the name of the area affected, e.g., `segment`, `cache`, `config`, `ui`.40Omit when the change is truly cross-cutting.4142### Description4344- Required. One short imperative sentence, no period at the end. The full header line (type +45 scope + description) must be **72 characters or fewer**. Aim for **50 characters or fewer for46 the description itself** — this almost always keeps the full header within budget regardless47 of type and scope length.48- Use the imperative mood: "add", not "added" or "adds". Never past tense or present-third-person:49 ✗ `added`, `fixed`, `bumped`, `implemented` → ✓ `add`, `fix`, `bump`, `implement`.50- **Never mirror the input's phrasing.** If the request uses past-tense words (`updated`, `added`,51 `bumped`, `was removed`, `got regenerated`), convert them to imperative before writing the52 description: `update`, `add`, `bump`, `remove`, `regenerate`.5354### Body5556Optional. Add context about _why_ the change was made, not _what_. The diff shows that.57Wrap at 72 characters.5859### Footer6061Use for:6263- `BREAKING CHANGE: <description>` (required when `!` is used; explains the break).64- Issue references: `Closes #123`, `Fixes #456`.65- Co-authors: `Co-Authored-By: Name <email>`.6667## Workflow68691. Run `git status` to review changed files.702. Run `git diff` and `git diff --cached` to inspect staged and unstaged changes.713. Identify the **type** from the table above. Ask yourself: does this change **remove, rename, or72 alter existing behavior** that callers depend on? If yes → it is a breaking change: use `!`73 after the type/scope **and** add a `BREAKING CHANGE:` footer. Both markers are always required74 together.754. Identify the **scope** from the files/area changed.765. Write a short **description** in the imperative mood.776. Add a **body** if the _why_ needs explanation.787. Add a **footer** for breaking changes or issue references.798. Stage the relevant files explicitly (avoid `git add -A`).809. Commit with a message that preserves multi-line formatting when body/footer are present.8182## Examples8384```text85feat(segment): add Ramadan segment with Aladhan API86fix(cache): always store mod time87docs(readme): update installation instructions88refactor(config): simplify option parsing logic89chore(deps): bump github.com/shirou/gopsutil/v490feat(segment)!: rename template property StartTime to Start9192BREAKING CHANGE: template strings using .StartTime must be updated to .Start93```9495## Validation Checklist9697- [ ] Type is one of the allowed values in .commitlintrc.yml98- [ ] The commit message respects the rules defined in .commitlintrc.yml99- [ ] Scope (if present) reflects the actual area changed100- [ ] Description is imperative mood, no trailing period101- [ ] Full header line (type + scope + description) is 72 characters or fewer102- [ ] Both `!` after type/scope **and** `BREAKING CHANGE:` footer are present whenever the change breaks existing behavior103- [ ] No sensitive files staged (.env, credentials, etc.)