Conventional Commits: The Complete Guide for Developers

By GitusAI · · 6 min read

Conventional Commits is a lightweight specification for commit messages. It gives every commit a predictable structure so that humans can scan history quickly and tools can read it, for example to generate changelogs or decide the next semantic version number.

The format

<type>[optional scope][!]: <description>

[optional body]

[optional footer(s)]

A real-world example looks like this:

feat(auth): add GitHub OAuth login

Users can now sign in with GitHub in addition to Google.

Closes #208

Common types

  • feat: a new feature (maps to a MINOR version bump in SemVer).
  • fix: a bug fix (maps to a PATCH bump).
  • docs: documentation-only changes.
  • refactor: a code change that neither fixes a bug nor adds a feature.
  • perf: a change that improves performance.
  • test: adding or correcting tests.
  • build / ci: changes to the build system or CI configuration.
  • chore: maintenance that does not touch src or tests.

Scopes

A scope in parentheses narrows down what part of the codebase changed: fix(api): ..., feat(ui): .... Pick a small, stable set of scopes per repository (usually packages, modules or layers) and document them so the team uses them consistently.

Breaking changes

Mark a breaking change with an exclamation mark after the type or scope, or with a BREAKING CHANGE: footer. Either one maps to a MAJOR version bump.

feat(api)!: remove v1 export endpoint

BREAKING CHANGE: clients must migrate to /v2/export.

Why teams adopt it

  • Automated changelogs and release notes from tools such as release-please or semantic-release.
  • Automatic version bumps driven by commit history.
  • Easier code review and bisecting, since the intent of each commit is obvious.
  • A shared vocabulary that new teammates pick up in minutes.

Enforcing it

Add commitlint with a Git hook (Husky or lefthook) to reject non-conforming messages locally, and run the same check in CI for pull requests. The friction is that people have to remember the format. That is where generation helps: GitusAI can produce Conventional Commits output directly from your staged changes, choosing the type and scope from the diff, so following the convention costs you no extra effort.

More from the blog