Conventional Commits: how to write good commit messages
The Conventional Commits standard explained with examples: types, scope, breaking changes, how to generate the changelog and version automatically, and how AI can help.
Open the history of an old project and you'll probably find messages like tweaks, wip, and should work now. They tell nothing to whoever needs to understand the code six months from now. Conventional Commits is a simple standard that fixes this.
The format
Each message follows this structure:
<type>(<optional scope>): <description>
<optional body>
<optional footer>Examples:
feat(login): add sign-in with Microsoft
fix(api): fix timeout in CSV export
docs: explain how to run the tests locallyThe most common types
feat: a new feature for the people who use the product.fix: a bug fix.docs: documentation only.refactor: a code change that doesn't change behavior.perf: a performance improvement.test: new or fixed tests.buildandci: build system, dependencies, and pipelines.chore: tasks that don't fit the categories above.
Scope and description
- The scope says where the change happened:
feat(checkout),fix(auth). Agree on scopes with your team. - Write the description in the imperative, present tense:
add,fix,remove. - Be specific:
fix shipping cost for ZIP codes without a street numberis better thanfix shipping. - Keep the first line short, around 72 characters at most. Details go in the body.
Body and footer
The body explains why the change was made, not what changed line by line (the diff already shows that). The footer holds references, such as the task number:
fix(checkout): recalculate shipping when the address changes
Shipping kept the cost of the previous address when the customer
changed the ZIP code after choosing a delivery option.
Refs: #482Breaking changes
When a change breaks compatibility, mark it with ! after the type or with BREAKING CHANGE: in the footer:
feat(api)!: remove the /v1/orders endpoint
BREAKING CHANGE: use /v2/orders, which paginates results.Why it's worth it
- The history becomes documentation: you can read what changed between two versions.
- Tools like semantic-release and release-please generate the changelog automatically.
- The version can be calculated automatically too:
fixbumps the patch,featbumps the minor, and a breaking change bumps the major. - Code review gets easier, because the type already tells you what to expect from the diff.
How to adopt it on your team
- Agree on types and scopes and write them down in the README or the contributing guide.
- Validate messages with commitlint, in a commit hook or in the pipeline.
- Start with the main types (
feat,fix,docs,refactor) and add the others as you need them.
AI commit messages in GitMuninn
Writing a good message every time takes effort. In GitMuninn, AI reads the diff and suggests the commit message, which you review before you confirm. It only runs when you ask, receives only the diff and the commit message, and nothing is stored on a server. You get 20 messages a month on the Free plan and unlimited on Pro and Business.

