CHANGELOG.md
The record of what changed, in developer language, and the only place change history accumulates. Every pull request writes its entry under one heading:
## Unreleased
### A headline saying what changed and for whom (YYYY-MM-DD)
What was wrong, what it is now, who it affects.
What it is for
So that a release is a deliberate act rather than a side effect of merging. A PR describes its change; the maintainer promotes Unreleased into ## x.y.z - <date> and moves the version, once. That split is why the file is checked at two levels: the file has to exist, and the Unreleased heading has to be in it - without the heading there is nowhere to write an entry that is not a version heading the PR just invented.
It is also the reason no other document grows a history section. A spec, an ARCHITECTURE page, a runbook all describe the present; git holds every past state; this file holds the curated record. Three competing histories only drift.
What goes in here
Prose, aimed at a person deciding whether this release touches them. What was wrong, what it is now, and what that means. One or two paragraphs beats a list of commit subjects, which the reader can get from git.
Every change. This output is complete and mechanical. The curated, plain-language story for a non-technical reader is a different output - RELEASE-NOTES.md, written at release, not the changelog with the boring lines removed.
What does not go in here
A version heading, or a version bump. Both are the maintainer's, at release. A PR that writes ## 1.4.0 has decided a release happened.
Internal codes. Ticket ids, rule numbers and backlog identifiers mean nothing to the reader six months later. Say what changed.
A second mechanism. A per-PR fragments folder was tried and removed: the conflict it avoided is resolved in seconds by keeping both lines, and nothing enforced the folder, so the realistic outcome was a repo whose history was half fragments and half direct edits.
More than one changelog
Two different repo shapes each split this file - never conflate them.
A repo that maintains more than one release line (a maintained 1.x branch beside main's 2.x) carries one changelog per line, each with its own Unreleased heading; a PR writes its entry under the heading on the branch it targets and bumps that line's version, PATCH by default.
A repo that ships more than one independently-versioned, independently-publishable unit from the same tree - rails/rails's thirteen gems (activerecord, actionpack, activesupport, ...), each with its own CHANGELOG.md in its own directory, all changing together on one branch - carries one changelog per unit instead of one at the root. A PR writes its entry under the heading of every unit it actually touches and bumps each one, PATCH by default; a change spanning two gems gets two entries and two version bumps, one per file, not one entry naming both.
These are independent axes (ADR-044): release lines split a changelog across branches over time, units split it across the same tree at once. A repo can face either, both, or - the common case - neither, and carry the one root CHANGELOG.md this page opens with.
Decisions behind it
- R18 - a PR describes its change under
Unreleasedand bumps the version itself, PATCH by default. The owner directs a different bump or an explicit no-bump per PR; the same rule extends to more than one release line and to more than one publishable unit, never a second kind of mechanism. - R25 - the PR that promotes
Unreleasedmoves the version, and the version is one fact restated nowhere unchecked. - R4 - history does not accumulate inside living documents. This file is where it goes instead.
The headings it must carry
- Unreleased. R18/R25 - a PR describes its change here; nothing else holds history, and drift 0 must not be reachable with no changelog at all
Reference
- Status. Required - part of the
coreprofile. - How it arrives.
fill-from-repo- scaffold the shell from the standard, then author the body from THIS repo's reality - never blind-copy the example prose (ARCHITECTURE, PRODUCT, specs) - Shipped form. read it in the standard's own tree
The rule that requires it
A PR MUST NOT add a version heading to the changelog and MUST NOT bump
