Commits
Conventional Commits, and why a commit message is written for the next developer.
The lesson first
In my first year, while rebuilding a Vue 2 app in Vue 3, my commit messages looked like this:
for backup
just for record
initial commit: error to be solvedI was committing to save my work, not to explain it. Months later, nobody could tell from the history what had changed or why, including me. Now every commit says what changed, in a format a tool can read too.
The format
type(scope): what changed, in the imperative- type: what kind of change it is (table below).
- scope: the feature or area, matching a folder name where possible.
- subject: lower case, no full stop, reads like a command: "add", not "added".
| Type | Use it for |
|---|---|
feat | A new feature or visible change for users |
fix | A bug fix |
refactor | A code change that doesn't change behaviour |
style | Formatting only (lint fixes, whitespace) |
docs | Documentation and written content about the project |
chore | Tooling, dependencies, config |
perf | A performance improvement |
test | Adding or fixing tests |
Real examples
From my portfolio's history:
feat(resume): implement PDF generation for résumé
feat(seo): per-page share metadata and built-in sitemap/robots
refactor(structure): move to src/ with feature folders per frontend rules
chore(tooling): adopt ultracite/biome and share cursor rules with claude
style: apply ultracite safe fixes
fix(animation): adjust bob animation duration and delayA few rules of thumb
One change per commit
If the message needs "and", it's probably two commits. A lint-only change
gets its own style: commit so it doesn't hide the real change in a diff.
Say why in the body when it isn't obvious
The subject says what. When the reason isn't clear from the diff, add a blank line and a short body:
fix(table): pass filters as an object instead of in the URL
The shared data table appends its own query string, so a URL that
already had "?" ended up with two, and paging params were lost.Commit when it works, not when you're worried
If I want a backup of half-finished work, that's what a branch and a push are
for. The commit on main should still explain itself.
Last updated on