Six sections, and why the list is short
The Keep a Changelog convention offers exactly six groups: Added, Changed, Deprecated, Removed, Fixed and Security. The shortness is the point. A reader arriving at release notes has one of a small number of questions — is there something new I can use, has something I depend on moved, do I have to act — and six headings answer all of them without a table of contents. Adding a seventh group for your team structure or your ticket system reintroduces the problem the convention exists to solve.
Two of the six are consistently underused. Deprecated is where you buy yourself the right to remove something later; an entry there names the replacement and, ideally, the release in which the old thing goes. Security is where a reader decides whether to upgrade today rather than at the next convenient moment, which is why a security entry should say what an attacker could do, not which function was patched.
What the prefix parser reads
The conventional-commit shape is a type, an optional scope in parentheses, an optional exclamation mark, a colon and the subject. The type is what routes the entry:
| Prefix | Section |
|---|---|
feat, feature, add | Added |
fix, bugfix, hotfix | Fixed |
perf, refactor, style, change, update | Changed |
deprecate | Deprecated |
remove, drop, revert | Removed |
security, or any scope named security | Security |
chore, ci, build, test, docs, deps | Held back as internal |
An exclamation mark before the colon, or the words BREAKING CHANGE anywhere in the line, adds the entry to a Breaking group at the top while leaving it in the section its type implies. That duplication is deliberate: someone skimming for what will break should not have to read the whole file, and someone reading the Added section should still see that the new thing arrives at a cost.
Why internal commits are separated rather than published
A release with forty commits often has fifteen that describe work on the repository rather than on the software — dependency bumps, formatting passes, test additions, documentation edits. They are real work and they belong in the log. Publishing them in release notes buries the four entries a reader needed among fifteen they cannot act on. So they are collected under their own heading here, visible enough that you can move one up if it genuinely changed behaviour, and out of the published block by default.
The one category worth watching is a dependency bump that fixes a known vulnerability. Its prefix says chore; its content belongs in Security. That is the case for reading the internal list rather than ignoring it.
Lines that do not parse
Anything without a recognised prefix is handed back rather than filed. This is a deliberate refusal: a subject like "tidy up the loose ends" could plausibly be a fix, a refactor or a removal, and a tool that picks one will be wrong often enough to make the whole file untrustworthy while looking complete. You can choose to fold them into Changed if your repository has no prefix convention and you would rather edit afterwards, but the default is to show you the pile.
Merge commits are the exception that is dropped outright. A merge subject describes branch topology, never a change, and no release note has ever been improved by one.
Version numbers and dates
The heading is written as a bracketed version and a date in year-month-day order, which sorts correctly and is unambiguous across regions. Leave the date blank while the release is still open and the heading reads Unreleased, which is the convention for the section at the top of the file that accumulates entries between tags. What the version number should be is a separate question with real rules — a breaking entry in this list means a major bump, an Added entry means at least a minor one — and the semantic version comparator covers the ordering and range side of that. For the file itself, the markdown table of contents generator handles long changelogs, and markdown preview shows how it renders before you commit.
Questions people ask
Can it read a raw git log?
It reads subject lines. Produce them with a format that emits one subject per line — a log format of hash and subject works, and the leading short hash is detected and stripped, or kept at the end of the entry if you tick that option. A full log with author, date and body paragraphs will not parse cleanly, because the body lines look like unprefixed subjects and land in the unparsed pile.
My repository does not use conventional commits at all.
Then everything lands in the unparsed list, which is honest but not much help. Set the unparsed option to Changed, generate the block, and rewrite the entries by hand. That is roughly the same work as writing the changelog from scratch, which is the actual cost of not having a prefix convention. The convention pays for itself at release time, not at commit time.
Why is a breaking change listed twice?
Once at the top under Breaking, so a reader scanning for upgrade risk finds it immediately, and once in the section matching its type, so the section is complete. A reader who only skims the top gets the warning; a reader working through Added sees the new feature and the fact that it replaced something. If you prefer a single listing, delete one of the two lines from the generated block.
Does it link entries to issues or commits?
No, and that is deliberate. Link formats depend on where the repository is hosted and on how your issue references are written, and generating half-correct links is worse than generating none. Trailing issue references in the form (#123) are stripped from the subject so the entry reads cleanly; add links back in the form your host expects once the grouping is settled.
Is anything I paste sent anywhere?
No. Parsing and formatting run in JavaScript in this tab, with no request made and nothing stored. Commit subjects for an unreleased version are among the more sensitive things a team pastes into a browser tool, so it is worth being explicit about that.