Keeping a changelog humans want to read

A git log is not a changelog. A short, curated record of notable changes tells users what an upgrade means for them.

A changelog entry grouping changes under added, changed and fixed headings

Commit messages are written for maintainers. A changelog is written for users, who want to know one thing: what does upgrading mean for me?

A simple format

## [2.4.0] - 2025-03-03

### Added
- `--watch` flag to rebuild on file changes

### Changed
- Default timeout raised from 5s to 30s

### Deprecated
- `legacyMode` option; will be removed in 3.0

### Fixed
- Crash when the config file is empty

### Security
- Updated XML parser to address an entity expansion issue

Group changes by type, newest version first, with dates.

What to include

  • New features users can see or use
  • Changes in behavior or defaults
  • Deprecations and removals
  • Bug fixes users might have noticed
  • Security fixes, clearly marked

What to leave out

  • Internal refactors, test changes and CI tweaks
  • Dependency bumps that don't affect users
  • "Fixed typo" commits

Make breaking changes impossible to miss

Put them first in a major release, explain why they happened and show how to migrate:

BREAKING: `parse()` now returns a Result instead of throwing.
Migrate: replace try/catch with `if (result.ok) { ... }`.

Keep an "Unreleased" section

Add entries as changes merge, under an Unreleased heading. At release time, rename it to the new version. This spreads the work out and avoids reconstructing months of history from commit logs the night before a release.

Generated vs. curated

Tools can draft changelogs from commit messages or pull request labels. That's a useful start — but a human pass to merge, reword and highlight what matters is what makes it readable.

Weekly digest

Releases, deep dives and the stories developers are talking about. No spam, unsubscribe any time.