A changelog is a file or page that lists the notable changes in each version of a project, newest first, with the release date of every version. Many projects follow the Keep a Changelog format, which groups each version's changes under six headings: Added, Changed, Deprecated, Removed, Fixed and Security. The eight changelog examples below cover different kinds of project, from an open-source library's CHANGELOG.md to a product updates page and an API changelog with shut-off dates, and each is followed by notes on why it works.
The projects are invented, so every entry can be copied and adapted. If you need the friendlier version of one release for users, with highlights and upgrade notes, start from the release notes template instead.
| Example | Format | Best for |
|---|---|---|
| ExampleOpen-source library | FormatCHANGELOG.md in Keep a Changelog format | Best forPackages that follow semantic versioning |
| ExampleCommand-line tool | FormatA yanked release and a security fix | Best forTools people install and pin to a version |
| ExampleWeb app | FormatDated product updates, no version numbers | Best forProducts that ship every week |
| ExampleMobile app | FormatStore “What's new” text | Best forShort notes read on a phone |
| ExamplePublic API | FormatDated entries with breaking changes and shut-off dates | Best forIntegrators who pin an API version |
| ExampleInternal platform | FormatAction required, then everything else | Best forShared services other teams depend on |
| ExampleGame | FormatPatch notes with old → new values | Best forBalance changes players will argue about |
| ExampleStyle guide | FormatRevision log per edition | Best forHandbooks, style guides and SOP libraries |
The Keep a Changelog format
Keep a Changelog, created and maintained by Olivier Lacan, is a short set of conventions for a CHANGELOG.md file. Version 1.1.0 defines a changelog as a curated, chronologically ordered list of notable changes for each version of a project. Its first principle is “Changelogs are for humans, not machines.” The others: every version gets an entry, changes of the same type are grouped, versions and sections can be linked to, the latest version comes first, each version shows its release date, and the file says whether the project follows semantic versioning.
| Heading | Use it for | Example line |
|---|---|---|
| HeadingAdded | Use it forNew features | Example line--cover option to set the cover image |
| HeadingChanged | Use it forChanges to existing behavior | Example lineChapters are ordered by the number in the file name |
| HeadingDeprecated | Use it forFeatures that will be removed later | Example linebook.toml still works and will be removed in 3.0.0 |
| HeadingRemoved | Use it forFeatures removed in this version | Example lineEPUB 2 output |
| HeadingFixed | Use it forBug fixes | Example lineFootnotes in block quotes keep their back-links |
| HeadingSecurity | Use it forFixes for vulnerabilities | Example lineThe verbose log no longer prints access keys |
Three more conventions do most of the work. An Unreleased section at the top collects changes as they are merged, so a release only needs a new heading. Dates are written YYYY-MM-DD, which can't be misread the way 04/05/2026 can. And a yanked release, one pulled for a serious bug or security problem, stays in the file with [YANKED] after its date. The file is called CHANGELOG.md; Keep a Changelog notes that some projects use HISTORY, NEWS or RELEASES, and argues for one consistent name so people can find it.
Semantic versioning in brief
Semantic Versioning 2.0.0, originally written by Tom Preston-Werner, gives each part of a MAJOR.MINOR.PATCH number a meaning, so the number alone tells readers how careful to be with an upgrade.
| Release | Increment it when you | The entry should show |
|---|---|---|
| ReleaseMAJOR: 2.4.0 → 3.0.0 | Increment it when youMake incompatible API changes | The entry should showEvery breaking change, first, with what to do about it |
| ReleaseMINOR: 2.3.1 → 2.4.0 | Increment it when youAdd functionality in a backward-compatible way | The entry should showWhat's new, plus anything deprecated and when it goes |
| ReleasePATCH: 2.3.0 → 2.3.1 | Increment it when youMake backward-compatible bug fixes | The entry should showThe fixes, and nothing a user has to change |
- 0.y.z is for initial development. Anything may change at any time, and 1.0.0 defines the public API. Flag breaking changes in a 0.x changelog anyway.
- Pre-releases and builds have their own marks. A hyphen starts a pre-release label (1.0.0-alpha) and a plus sign starts build metadata (1.0.0+20130313144700).
- “v1.2.3” is a tag name. The semantic version is 1.2.3, so write version headings without the v.
- A released version never changes. If a minor release broke compatibility by mistake, SemVer's FAQ says to fix it in a new minor release that restores compatibility, and the changelog should say so.
Open-source library CHANGELOG.md example
A library's readers are developers deciding whether an upgrade is safe. Here is a complete CHANGELOG.md for mdbinder, an invented tool that turns a folder of Markdown chapters into an EPUB file.
CHANGELOG.md (an invented library, Keep a Changelog format)
# Changelog
All notable changes to mdbinder are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- `--cover` option to set the cover image from the command line.
## [3.0.0] - 2026-10-02
### Removed
- **Breaking:** EPUB 2 output. mdbinder now writes EPUB 3 only. If you
need EPUB 2, stay on 2.x, which gets security fixes until 2027-04-01.
- **Breaking:** the `book.toml` config file, deprecated in 2.4.0.
Run `mdbinder migrate-config` to convert it to `book.yaml`.
### Changed
- Chapters are ordered by the number at the start of the file name
(`01-arrival.md`), not alphabetically. Files without a number go last.
### Fixed
- Footnotes inside block quotes keep their back-links (#214).
## [2.4.0] - 2026-07-15
### Added
- `toc_depth` setting in `book.yaml` for the table of contents.
### Deprecated
- `book.toml`. It still works in 2.x and will be removed in 3.0.0.
## [2.3.1] - 2026-06-03
### Fixed
- Curly quotes in chapter titles are no longer straightened in the
table of contents (#198).
[unreleased]: https://example.com/mdbinder/compare/v3.0.0...HEAD
[3.0.0]: https://example.com/mdbinder/compare/v2.4.0...v3.0.0
[2.4.0]: https://example.com/mdbinder/compare/v2.3.1...v2.4.0
[2.3.1]: https://example.com/mdbinder/compare/v2.3.0...v2.3.1Why it works. The header says which format and which versioning scheme the file follows, as Keep a Changelog asks. The 3.0.0 entry leads with its two breaking changes and says what to do about each, and the config file was deprecated one minor version earlier, in 2.4.0, the order SemVer's FAQ recommends. Issue numbers stay because these readers will click them, and the link references at the bottom turn every version heading into a link to its diff.
Command-line tool with yanked release
A tool people pin to a version needs the uncomfortable entries most: the release that was pulled and the security fix that replaced it.
[1.9.1] - 2026-09-18
Security
- The
--verboselog no longer prints the storage access key. If you ran 1.9.0 with--verbose, rotate that key and delete the old logs. Advisory SK-2026-03.
Fixed
- Restores no longer stop at the first file with a non-ASCII name (#341).
[1.9.0] - 2026-09-10 [YANKED]
Pulled on 2026-09-12 because --verbose wrote access keys to the log. Use 1.9.1.
Added
--exclude-from FILEreads exclusion patterns from a file, one per line.
Changed
- The default compression level is now 6 (was 3). Backups are smaller and take longer to write; pass
--level 3for the old speed.
Why it works. The yanked version stays in the file, marked the way Keep a Changelog recommends, with the reason and the version to use instead, so anyone who pinned 1.9.0 can see why it is no longer offered. Security comes first in 1.9.1 and tells readers what to do, not only what changed. The Changed line names the cost of the new default and how to opt out.
Web app product updates page
Nobody installs a version of a web app, so a product changelog is organized by date. Its readers are customers, not developers.
Speaker names carry over · November 4, 2026
Name a speaker once and Quotebook suggests the same name in your later interviews with that person. You confirm each suggestion. Read more: How speaker names work.
- Improved: Word exports keep timestamps in their own column, so you can sort quotes by time.
- Fixed: Search no longer finds words in interviews you deleted.
Fixes · October 21, 2026
- Fixed: Uploads over 2 GB no longer fail at 99 percent on slow connections.
Share a highlight · October 7, 2026
Select a passage in a transcript and choose Share highlight to send a link to that passage with its audio. Links expire after 30 days; change that in Settings › Sharing.
Why it works. Each headline names the change and the date follows it, because readers scan the page for what is new, not for a day. Each entry starts with what the reader can now do and points to the help article. The quiet fortnight still gets its one line, which tells customers the product is looked after. And “You confirm each suggestion” answers the question a journalist would ask before trusting the feature with a source's name.
Mobile app store changelog
Store notes are read in a list of other updates, on a small screen. Three lines are plenty.
- Tide alerts: get a notification an hour before high water at any saved harbor. Turn them on in Settings › Alerts.
- Wind arrows now show gusts as well as average speed.
- Fixed: the home screen widget no longer shows yesterday's tides after midnight.
Why it works. The change most people will notice comes first and says where to find it. The text doesn't open with “What's new in 4.2”: the store already shows the version number, and the first line is the one a reader sees before deciding to read on. There is no “bug fixes and performance improvements” line, which tells the reader nothing. The full changelog on the app's website, under the same version number, carries the detail.
API changelog with deprecations
Integrators read an API changelog to answer one question: will my code break, and when? Every entry says which versions it affects.
2026-11-02 · New API version 2026-11-02
These changes apply only when you request version 2026-11-02. Integrations pinned to an earlier version see no change.
- Breaking:
GET /v1/reservationsreturns 50 results per page by default (was 100). Passlimit=100to keep the old page size. - Added:
cancellation_deadlineon the Reservation object, as an ISO 8601 date and time.
2026-10-19 · All versions
- Deprecated:
POST /v1/rates/bulk. UsePOST /v1/rate_jobs, which returns a job ID you can poll. The old endpoint stops responding on 2027-05-03, and its responses now carry Deprecation and Sunset headers. Migration guide: Bulk rate updates. - Fixed:
422errors for an invalid check-in date name the field inerror.param.
Why it works. The breaking change says exactly what to send to keep the old behavior. The deprecation names the replacement, the shut-off date and the migration guide, and the API repeats the warning in its responses: the Deprecation header (RFC 9745, March 2025) marks a resource as deprecated, and the Sunset header (RFC 8594, May 2019) gives the date it is expected to stop responding. Several public APIs name versions by date. Stripe's sample requests send a Stripe-Version header that starts with a date, and GitHub's send an X-GitHub-Api-Version date. The technical writing examples show how the rest of a developer docs set fits around it.
Internal platform changelog
Inside a company, the readers are other engineering teams, and they want to know whether they have to do anything.
Week of 2026-10-19
Action required by 2026-11-16
- The
node18build image is retired on 2026-11-16. Changeimage: node18toimage: node22in.ci.yml. Still on node18: payments-web and search-indexer (owners emailed on 2026-10-20).
No action needed
- Branches of the same repository now share a build cache. Median build time on main fell from 9 min 40 s to 6 min 5 s.
- Test reports over 10 MB are no longer cut off in the build summary.
Questions: #build-platform. Next entry: 2026-10-26.
Why it works. The split answers the reader's only question before any detail. The action has a date, the exact line to change and the names of the teams still affected. The improvement comes with a before-and-after number instead of an adjective.
Game patch notes example
Patch notes are a changelog for an audience that reads every number. Balance changes show the old value and the new one.
The Harbor Update · Patch 1.6.0 · 2026-11-05
New
- The Saltmarsh harbor district, with four new quests and the Ferryman's shop.
Balance
- Longbow damage 42 → 38. Draw time 0.9 s → 0.8 s.
- Healing tonic cooldown 20 s → 30 s.
Designer's note: the longbow was the best weapon at every range. It should win at long range and lose up close. The faster draw keeps it fun to use.
Fixed
- Saving during the bell tower cutscene no longer locks the camera when you load the game.
Known issues
- Controller vibration doesn't work in Saltmarsh. A fix is planned for 1.6.1.
Why it works. Old → new values let players judge each change for themselves. The designer's note gives the reason for the most disputed change, which players would otherwise guess at. Known issues come with the planned fix, so nobody reports them again.
Style guide revision log
Documents change too. A style guide needs a changelog more than most, because editors apply its rules from memory and need to know when one moved.
Edition 5.2 · 2026-09-01
Changed
- Percent: use the % sign with figures in all copy (was: “percent” in body text, % only in tables and charts).
- Headlines: sentence case in every section. Sports moves over from title case.
Added
- Entry: livestream, one word, as a noun and a verb.
Removed
- The rule against starting a sentence with “But”. It was never enforced.
Applies to copy filed from 2026-09-01. Archive stories are not updated.
Why it works. Each change records the old rule as well as the new one, so a copy editor can tell an older story from a mistake. The last line says when the edition takes effect and that the archive stays as it is. The same log works for an SOP library (see the SOP examples, each of which ends with a revision line) and for a book's style sheet.
Changelog vs release notes
The two often start from the same change, but they serve different readers. Here is the widget fix from the Tidewatch store text above, written once for each:
| In CHANGELOG.md, for developers | In the release notes, for users | |
|---|---|---|
| The line | In CHANGELOG.md, for developersFixed: the widget timeline reloads at local midnight instead of at the next app launch (#412). | In the release notes, for usersFixed: the home screen widget no longer shows yesterday's tides after midnight. |
| It tells the reader | In CHANGELOG.md, for developersWhat the code now does, and where the discussion is | In the release notes, for usersWhat they saw go wrong, in their words |
| It leaves out | In CHANGELOG.md, for developersHow the bug looked on a phone | In the release notes, for usersThe mechanism and the issue number |
Put the issue number in the store text and no user can do anything with it. Leave the mechanism out of the changelog and the next developer can't tell what changed, or whether a later bug is the same one coming back. Keep one source of changes and write both versions from it, so the two never disagree about what shipped.
| Changelog | Release notes | |
|---|---|---|
| Reader | ChangelogDevelopers, integrators, anyone upgrading | Release notesUsers and customers, support and sales |
| Covers | ChangelogEvery notable change in every version | Release notesOne release, the changes people will notice |
| Shape | ChangelogTerse lines grouped by type | Release notesHighlights first, then short lists and upgrade steps |
| Lives in | ChangelogCHANGELOG.md, a changelog page, the API docs | Release notesRelease emails, in-app notices, store pages, a blog |
| Kept for | ChangelogAs long as the project exists | Release notesThe weeks around the release |
How to write changelog entries
- Start from what changed for the reader. Use the names on the screen or in the API, not the names of internal modules.
- One change per line, breaking changes first. Mark them “Breaking” even under Removed or Changed, so readers scanning for the word find it.
- Say what to do. A deprecation names its replacement and its removal version or date. A breaking change gives the migration step or links to it.
- Use numbers instead of adjectives. “Builds take 6 minutes instead of 10” beats “much faster builds”.
- Write the entry when the change merges. Add a line under Unreleased in the same pull request. Reconstructing a month of changes on release day is when entries go missing.
Tells the reader what changed
- Search results load in under a second for libraries of 10,000 notes (was about 4 seconds)
- Removed: the /v1/export endpoint. Use /v2/exports; see the migration guide
- Dates in CSV exports use YYYY-MM-DD in every language setting
- Security: session cookies are now marked Secure and HttpOnly
Tells the reader nothing
- Bug fixes and performance improvements
- Various improvements to export
- Refactored session handling
- Updated dependencies
If you keep the changelog in Strokes, ask the Strokes Assistant to review a new entry against the rest of the file. It flags inconsistencies such as a version without a date, a breaking change filed under Fixed or a deprecation with no removal date.
Building a changelog from commits
Conventional Commits 1.0.0 calls itself “a lightweight convention on top of commit messages”. Each message starts with a type: fix commits map to PATCH releases, feat commits to MINOR releases, and a BREAKING CHANGE footer or a ! after the type to MAJOR. Its site lists automatic changelogs among the reasons to adopt it, and release tools can turn such a history into a sorted draft.
Five of the commits merged between 2.4.0 and 3.0.0
feat!: drop EPUB 2 output
fix: keep footnote back-links inside block quotes (#214)
refactor: split the parser into two modules
chore(deps): bump yaml to 2.6.1
feat!: remove support for book.tomlFrom those five commits, three lines reach the 3.0.0 entry in the file above: two breaking entries under Removed (EPUB 2 and book.toml) and one under Fixed (the footnotes). The ! marks are also what make the next version 3.0.0. The refactor and the dependency bump disappear, because nothing changed for the reader. That editing step is the point. Keep a Changelog's warning still holds: commit logs are full of noise, because a commit records a step in the work, while a changelog entry records a difference someone will notice.
Common changelog mistakes
- Leaving out the awkward parts. Keep a Changelog warns that a changelog mentioning only some changes can be as dangerous as none. Deprecations, removals and breaking changes are the lines people most need.
- Dates people can misread. 04/05/2026 is April in the US and May in most of Europe. Use 2026-04-05.
- Deleting a bad release. Mark it [YANKED], say why and point to the replacement.
- A version number that contradicts the entry. A “Breaking” line under a PATCH release tells users the number can't be trusted.
- Internal shorthand in a public changelog. Code names and team names mean nothing to customers.
Frequently asked questions
Do I need semantic versioning to keep a changelog?
No. A changelog works with any versioning scheme, including dates or plain release numbers, and a web app can use dates alone. Semantic versioning helps because the number itself signals risk: a new MAJOR version means breaking changes, which the changelog then explains. Whatever you use, say so at the top of the file.
Does marking a release [YANKED] remove it?
No. In a Keep a Changelog file the mark only tells readers. To stop new installs, yank the version in the package registry as well. On PyPI, installers skip a yanked release unless a project pins exactly that version, and Cargo won't pick a yanked crate version for a project without an existing lockfile. Neither registry deletes the files.
Should a changelog list refactors and dependency updates?
Not in a public changelog, unless the reader feels the effect. A refactor that changes nothing for users stays in the commit history. A dependency bump earns a line when it fixes a vulnerability, raises a minimum version or changes behavior. An internal platform changelog can be broader, because other teams do feel a new build image.



