Conventional Commits & Changelog

Write a commit message in the conventional style, with a prefix like fix: or feat: that other tools can read, and turn a list of them into a grouped changelog with the version bump worked out. A breaking change is marked before the colon or in a footer; in the description it does nothing.

How to use it

On the first half you build a single commit message from a type, an optional scope and a description, and it is checked against the convention as you write it.

  1. Compose a message Type, optional scope, imperative description. The linter flags the usual mistakes.
  2. Paste a release worth of commits Straight from git log --oneline. Hashes are stripped automatically.
  3. Read the bump Breaking gives major, feat gives minor, everything else patch. That is the whole rule.
Full instructions

In depth

Writing commit messages that machines can read and humans still like

What the conventional commits format actually asks for, how the builder and the changelog generator work, a complete example with version bumps, and the mistakes that trip up most teams in the first month.

Screenshot: The convention exists for the changelog
The convention exists for the changelog as it appears when the page opens.

The problem with free-form messages

Most projects start with commit messages like 'fixed stuff' or 'updates'. That works until someone asks for a changelog, or until a CI pipeline needs to decide whether to bump the major version or the patch.

Conventional commits solve this by putting a machine-readable type at the front of every message. feat means a new feature. fix means a bug fix. The rest of the message is still human language, but that one word at the start gives tools enough to sort, group, and version automatically.

The convention is simple. The first line reads type(scope): description, where scope is optional. A body and footers can follow, separated by a blank line. That is the whole specification.

The builder on the right-hand side

The tool has two halves. The right rail builds a single commit message. The left side shows the result and, further down, generates a changelog from many commits.

Start with Type. The dropdown offers eleven choices: feat, fix, docs, refactor, perf, test, build, ci, style, chore, and revert. Each one has a short note beside it explaining what it covers. Pick the one that describes the purpose of the change, not what files it touched.

Scope is a text field. It is optional. If you use it, put a short word that names the area of the project: auth, api, ui, payments. The scope appears in parentheses after the type and helps group related changes in the changelog.

Description is the main summary. Keep it imperative and lower case, with no full stop at the end. Think of it as completing the sentence 'this commit will ...' so 'add passkey sign-in' rather than 'added passkey sign-in'. The tool hints at this with the note 'Imperative, lower case, no full stop'.

Body is a text area for the longer explanation. It answers the question 'why?' rather than 'what?'. It is optional, and many commits do not need one.

Marking a breaking change correctly

The checkbox labelled This is a breaking change does two things. It puts a bang before the colon in the first line, turning feat into feat!. And it opens a field labelled What breaks, where you describe what callers or users need to change.

The page warns you directly: an exclamation mark inside the description does nothing. The bang must appear between the type and the colon, or a BREAKING CHANGE footer must appear in the body. Those are the only two positions that tools look at.

The Closes issues field takes numbers separated by spaces. Writing 42 108 produces footer lines that link the commit to those tickets. Some hosting platforms will close the issues automatically when the commit is merged.

The linter and the message it produces

As you fill in the fields, the Commit message text area at the top left updates live. It shows the assembled first line, the body, and any footers. The linter runs alongside it and flags common mistakes.

A description that starts with a capital letter gets flagged. A first line longer than 72 characters gets a warning, because git log and most hosting interfaces will cut it off there. A missing type or an empty description is rejected outright.

The Copy message button puts the finished text on your clipboard. From there you paste it into your terminal as the argument to git commit -m. The tool does not run git for you. It writes text, and you decide when and where to use it.

Generating a changelog from a list of commits

Below the single-commit builder is a larger text area labelled Commits for a changelog. Paste a batch of first lines here, one per line. They can come straight from git log --oneline. If the lines start with commit hashes, those are stripped automatically.

Next to it is Current version, which defaults to 1.0.0. The tool reads every line, sorts them by type, and produces a grouped changelog in Markdown. Features sit under one heading, fixes under another, and so on.

Two checkboxes affect what appears. Include chores in the changelog adds chore commits, which are often left out because they are internal housekeeping. Include unconventional commits keeps any line that does not follow the format, listed under a separate heading so nothing disappears without warning.

How the version bump is decided

Under the changelog sits the version bump. The rule is short. If any commit is a breaking change, the major number goes up. If there are no breaking changes but at least one feat, the minor number goes up. If there are only fixes, docs, refactors, and other non-feature types, the patch number goes up.

So if your current version is 1.3.2 and you paste five commits that include one feat and three fixes, the suggested next version is 1.4.0. Add a breaking change and it jumps to 2.0.0.

Below 1.0.0 the rules are looser by convention. Many projects treat 0.x releases as unstable and do not bump the major number for breaking changes until they reach 1.0.0. The tool follows the strict rule because it cannot guess your project's policy.

A full example with five commits

Set Current version to 2.1.0. Paste these five lines into the changelog area:

feat(auth): add passkey sign-in. fix(api): return 404 for missing users. docs: update the getting started guide. fix(ui): align the submit button on mobile. chore: bump dependencies to latest.

The changelog groups them into Features, Bug Fixes, Documentation, and Chores (if that checkbox is on). The bump reads 2.2.0, because there is one feat and no breaking changes.

Now add a sixth line: feat!(auth): remove password login. The bang makes it breaking. The bump changes to 3.0.0 and the changelog adds a prominent breaking changes note.

Mistakes that cause trouble in practice

  • Putting the bang inside the description instead of before the colon. Writing 'feat: remove password login!' is just a normal feat. Write 'feat!: remove password login' for a breaking change.
  • Making one commit do two things. If a commit adds a feature and fixes a bug, the changelog can only file it under one type. Split it into two commits.
  • Using past tense. 'Added' instead of 'add' is not a strict error, but it reads badly in a generated changelog that says 'this release will: added passkey sign-in'.
  • Forgetting the colon after the type. Writing 'feat add passkey sign-in' without the colon makes the line unparseable.
  • Starting the description with a capital letter. The convention calls for lower case. The linter catches this, but many people ignore it until their generated changelog is a mix of cases.
  • Writing a novel in the first line. Keep it under 72 characters. Move the detail into the body.

When this tool is not the right fit

If your project already has commit hooks that lint messages as they are written, you may not need a separate builder. The builder is most useful when you are learning the format or when you are writing a batch of commits for a squash merge.

If you want a changelog that pulls from a remote repository automatically, a CI tool like semantic-release does the reading and the publishing in one step. This tool is for the manual version of that workflow.

If your team does not use conventional commits and has no plan to start, the changelog generator will still try to group whatever you give it, but the output will be less useful because most lines will land under the 'other' heading.

No data leaves your browser

The commit builder, the linter, and the changelog generator all run in your browser. Nothing you type is sent to a server. This matters when the description mentions a security fix or a client name that should not appear in a third-party log.

There is no account, no saved history, and no telemetry on what you paste. Close the tab and the session is over. You can prove it by turning off your network connection and running through the whole workflow. The builder, the linter, and the changelog all keep working exactly the same way.

Help

The convention exists for the changelog

On the first half you build a single commit message from a type, an optional scope and a description, and it is checked against the convention as you write it. On the second, a pasted list of commits is sorted into changelog sections, with the version bump those commits imply worked out from what is in them.

Compose a message

Type, optional scope, imperative description. The linter flags the usual mistakes.

Paste a release worth of commits

Straight from git log --oneline. Hashes are stripped automatically.

Read the bump

Breaking gives major, feat gives minor, everything else patch. That is the whole rule.

Nothing is committed for you

This writes text. Copy it into your editor or pass it to git commit -m yourself.

Good to know

Mark breaking changes properly

Either "feat!: …" with the bang before the colon, or a BREAKING CHANGE: footer. A "!" inside the description does nothing at all.

Imperative mood

"add" not "added". The message completes the sentence "this commit will…", which is why git's own templates read that way.

Scope is optional and useful

It groups the changelog usefully — "auth", "api", "ui" — without needing a separate label system.

Common questions

Do I have to use conventional commits?
No, but automated versioning and changelogs need some machine-readable convention, and this is the one with the most tooling behind it.
What if a commit does two things?
Split it. That is usually the real answer, and it makes the changelog readable as a side effect.
Does a breaking change always mean a major version?
Under semver, yes — above 1.0.0. Below 1.0.0 the rules are looser by convention, which is part of why 0.x exists.
How long should the first line be?
Under 72 characters. Beyond that git log and most hosting interfaces truncate it.