How to Write a Changelog: Format, Examples, and Templates

How to create and maintain a changelog for your project. Covers the Keep a Changelog format, semantic versioning, automation, and ready-to-use templates.

· · 7 min read

Last updated: February 28, 2026

markdown changelog how-to

A changelog is a file that lists notable changes for each version of a project. It helps users and contributors understand what changed, why it changed, and when. The standard format is a markdown file named CHANGELOG.md at the root of your repository.

The Keep a Changelog Format

The most widely adopted format is Keep a Changelog, which organizes entries by version and change type.

# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com),
and this project adheres to [Semantic Versioning](https://semver.org).
## [Unreleased]
### Added
- New API endpoint for bulk operations
## [1.2.0] - 2026-03-01
### Added
- Custom domain support for Pro users
- Dark mode toggle in the editor
### Changed
- Improved PDF export rendering speed
### Fixed
- Links with parentheses in URLs now render correctly
- Fixed timeout on large file uploads
## [1.1.0] - 2026-02-15
### Added
- Markdown table support in the editor
- CLI flag for custom output directory
### Deprecated
- The `--legacy` flag will be removed in v2.0
### Removed
- Dropped support for Node.js 16
### Security
- Updated dependencies to patch CVE-2026-1234

Change Types

Keep a Changelog defines six categories:

TypeWhen to Use
AddedNew features or functionality
ChangedModifications to existing features
DeprecatedFeatures that will be removed in a future version
RemovedFeatures that were removed in this version
FixedBug fixes
SecurityVulnerability patches and security improvements

Use only the categories that apply to each release. Skip empty categories.

Writing Good Changelog Entries

Be specific. Describe what changed, not that something changed:

<!-- Vague -->
- Improved performance
<!-- Specific -->
- Reduced API response time from 800ms to 120ms for list endpoints

Write for users, not developers. A changelog is for people who use your software. Internal refactors that do not affect behavior do not belong here.

<!-- Internal detail users don't care about -->
- Refactored auth module to use strategy pattern
<!-- User-facing change -->
- Login now supports Google and GitHub OAuth

Link to relevant issues or PRs when helpful:

- Fixed file upload timeout on files over 10MB ([#142](https://github.com/user/repo/issues/142))

Use present tense or past tense consistently. Both conventions are common. Pick one and stick with it:

<!-- Present tense -->
- Add custom domain support
- Fix timeout on large uploads
<!-- Past tense -->
- Added custom domain support
- Fixed timeout on large uploads

Semantic Versioning and Changelogs

Changelogs pair well with Semantic Versioning (SemVer):

Version ChangeWhenExample
Major (X.0.0)Breaking changesRemoving an API endpoint, changing default behavior
Minor (0.X.0)New features (backwards-compatible)Adding a new CLI flag, new API endpoint
Patch (0.0.X)Bug fixes and security patchesFixing a rendering bug, patching a vulnerability

The changelog makes SemVer meaningful. Users can look at the version number to understand the scope of changes, then read the changelog for details.

The Unreleased Section

Keep an [Unreleased] section at the top for changes that have been merged but not yet released:

## [Unreleased]
### Added
- Webhook support for publish events
### Fixed
- Editor cursor position reset on save

When you cut a release, move the unreleased items under a new version heading with today’s date and start a fresh [Unreleased] section.

Changelog vs Release Notes

AspectChangelogRelease Notes
AudienceDevelopers, contributorsEnd users, broader audience
ToneTechnical, conciseMarketing-friendly, may include screenshots
FormatBullet points by categoryNarrative with highlights
LocationCHANGELOG.md in repoGitHub Releases, blog post, email
ScopeEvery notable changeHighlights and key changes

Many teams maintain both: a changelog as the technical record and release notes as the user-facing announcement. For more on this distinction, see Release Notes vs Changelog.

Automating Changelogs

Several tools can generate changelogs from Git commits or pull requests:

ToolApproach
Conventional CommitsStandardized commit messages (feat:, fix:, chore:) parsed by tools
changesetsPR-level change descriptions, merged into changelog on release
standard-versionBumps version and generates changelog from conventional commits
release-pleaseGoogle’s tool for automated releases and changelogs from conventional commits
GitHub ReleasesAuto-generates release notes from PR titles

Conventional Commits

The convention formats commit messages as:

type(scope): description
feat(api): add bulk delete endpoint
fix(editor): resolve cursor jump on paste
docs(readme): update installation instructions

Tools parse these into changelog categories: feat maps to “Added”, fix maps to “Fixed”, and so on.

Automation helps, but review the output before publishing. Auto-generated entries often need editing for clarity and completeness.

Templates

Basic Changelog

# Changelog
## [Unreleased]
## [1.0.0] - 2026-03-04
### Added
- Initial release
- Core publishing functionality
- CLI with `publish` and `list` commands
- Free and Pro tiers

Detailed Changelog

# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com),
and this project adheres to [Semantic Versioning](https://semver.org).
## [Unreleased]
### Added
- Webhook notifications for publish events
## [2.1.0] - 2026-03-01
### Added
- Custom domain support ([docs](/docs/guides/custom-domains))
- Bulk publish command: `mdtolink publish *.md`
### Changed
- Default expiry for free tier increased from 3 to 7 days
### Fixed
- PDF export now preserves syntax highlighting colors
- Fixed 404 on slugs containing periods
## [2.0.0] - 2026-02-01
### Changed
- **Breaking:** API authentication now requires Bearer tokens
(API keys still work but are deprecated)
### Removed
- Dropped support for Node.js 16
### Security
- Updated marked to v15.0.0 (XSS fix)

Minimal Changelog (For Small Projects)

# Changelog
## 1.2.0 (2026-03-04)
- Add dark mode
- Fix image rendering in tables
## 1.1.0 (2026-02-15)
- Add table support
- Improve CLI output formatting
## 1.0.0 (2026-01-01)
- Initial release

FAQ

Where should the changelog file live?

Put CHANGELOG.md in the root of your repository. This is the standard location. GitHub, GitLab, and most tools look for it there.

How is a changelog different from git log?

A git log contains every commit, including typo fixes, merge commits, and internal refactors. A changelog is curated: it lists only changes that matter to users, grouped by version and category.

Should I include internal changes in the changelog?

No. Refactors, dependency updates (unless security-related), and code cleanup that do not affect users should be left out. The changelog is for user-facing changes.

How often should I update the changelog?

Update it with every pull request that introduces a notable change. Use the [Unreleased] section to collect changes between releases. This avoids a last-minute scramble when cutting a release.

Publish Your Changelog

Write your changelog in markdown, then share it with your team or users. The MDtoLink editor lets you preview your changelog in real time. When it’s ready, publish it to a shareable URL with one click using mdtolink publish CHANGELOG.md.

For the full markdown syntax reference, see the markdown cheat sheet. For tips on document structure, see the headings guide.


David Schemm
David Schemm

Founder, MDtoLink

David builds developer tools and writes about markdown workflows, documentation, and AI-assisted publishing.

Publish your markdown to a shareable URL

One command. Free to start. No credit card.