How to Keep a CHANGELOG.md Your Team Will Actually Read
A CHANGELOG.md people actually read is a curated, dated list of what changed — grouped by type, newest first. It's not a copy of your commit log.
Quick answer
Keep CHANGELOG.md in the Keep a Changelog format: an Unreleased section at the top, then one section per version below it, newest first. Inside each version, group entries under the six standard headings — Added, Changed, Deprecated, Removed, Fixed, Security — and write one plain-language line per change. Why bother? Because it's built for humans, not machines. A reader scanning the file should know what changed and whether it affects them without opening a diff.
Step-by-step
Set up the file structure
Start the file with an Unreleased section, then list versions below it in reverse-chronological order — newest at the top:
# Changelog
## [Unreleased]
## [1.2.0] - 2026-07-14
### Added
- Dark mode toggle in Settings.
### Fixed
- Export no longer drops the last line of long documents.Use ISO 8601 dates (YYYY-MM-DD). It's the format Keep a Changelog recommends, and it's worth adopting on principle: it sorts correctly as plain text, and nobody has to guess whether 03/04/2026 means March 4th or April 3rd.
Use the six standard categories
Only include the categories that have entries for a given version:
- Added — new features.
- Changed — changes to existing behavior.
- Deprecated — features on their way out.
- Removed — features that are gone.
- Fixed — bug fixes.
- Security — vulnerability patches.
If you follow Semantic Versioning, say so near the top of the file. It tells readers what a version bump implies before they read a single entry.
Write entries for a reader, not a commit
"Fixed stuff" isn't an entry. "Export no longer drops the last line of long documents" is. Name the feature or the bug specifically enough that someone who didn't write the code still gets it. For more on writing clear technical Markdown day to day, see our style guide for docs.
Reference exact values in code
When an entry involves a CLI flag, config key, or version string, put it in inline code so there's no ambiguity — --verbose, not verbose. See when to reach for inline code versus a fenced block for the difference.
Common problems and fixes
Everyone editing the same file causes merge conflicts
On an active project, multiple people adding lines to the same spot in CHANGELOG.md is a reliable way to generate merge conflicts. Some projects solve this with a fragment-file workflow: tools like Towncrier have each contributor add a small, separate file for their change, then assemble the full changelog from those fragments at release time. For a smaller team, a lighter version of the same idea works fine — keep each entry to one line, and merge changelog updates often so conflicts stay small when they happen at all. Either way, consistent formatting across contributors matters; see keeping your Markdown formatting consistent.
The changelog turns into a wall of commit messages
Pasting git log output into CHANGELOG.md isn't a changelog. It's full of noise — merge commits, one-word messages, documentation-only commits that mean nothing to a reader deciding whether to upgrade. Write, or rewrite, entries afterward in plain language, grouped by category, even if you start from skimming the commit history.
Unreleased never gets updated until release day
The fix here is procedural, not technical: add "update CHANGELOG.md" to your pull-request checklist so it happens alongside the change, not as a scramble right before a release.
Frequently Asked Questions
What should go in a CHANGELOG.md file?
Each version gets its own dated section listing what changed, grouped under standard headings: Added, Changed, Deprecated, Removed, Fixed, and Security. Keep entries short and specific — one line per change, written for someone skimming, not for someone who already read the diff.
What is the Unreleased section for?
It's a placeholder at the top of the file where you log changes as you make them, before they ship in a numbered release. At release time, you rename Unreleased to the new version number and date, then start a fresh empty Unreleased section above it.
Should a changelog just be a list of git commits?
No. Commit logs are full of noise — merge commits, typo fixes, obscure one-word messages — that don't tell a reader what actually changed for them. A changelog is a curated, human-readable summary; write it separately from your commit history, even if you draft it from skimming the commits.
What date format should a changelog use?
ISO 8601: YYYY-MM-DD. It sorts correctly as plain text, and it doesn't leave anyone guessing whether 03/04/2026 means March 4th or April 3rd.
How do teams avoid merge conflicts when everyone edits the same CHANGELOG.md?
Some projects have each contributor add a small fragment file for their change instead of editing the shared file directly, then assemble the full changelog from those fragments at release time. For smaller teams, a lighter fix works too: keep entries short, one per line, and merge often so conflicts stay small.
Doing this with Carets
A CHANGELOG.md is just a Markdown file with headings, dates, and short list entries. That's exactly the kind of file Carets is built to edit. Syntax highlighting keeps the structure easy to scan while you're writing — ## [1.2.0] - 2026-07-14 and each category heading stand out from the entries underneath them. Files, projects, and tags mean CHANGELOG.md can sit right alongside a project's other notes and docs instead of living in a separate app. And because Carets is native and fast on iPhone, iPad, and Mac, adding an Unreleased entry the moment you ship a fix takes seconds, wherever you happen to be working.
To be clear about scope: Carets is a fast place to write and edit the file. It doesn't generate changelog entries from your commits or manage fragment files for you — for that, a dedicated tool like Towncrier still does the job.
Carets is free to try on iPhone, iPad, and Mac — download it from the App Store.