Lesson 117 of 12110 min read

CHANGELOG.md: Maintaining a Human-Readable Version History

Learn how to maintain a genuinely useful CHANGELOG.md file, following the Keep a Changelog convention, either by hand or fully automated.

Author: CodersNexus

CHANGELOG.md: Maintaining a Human-Readable Version History

The previous two lessons established how Semantic Versioning and Conventional Commits together enable automated version bumping and changelog generation. This lesson focuses on the actual artifact that process produces: a `CHANGELOG.md` file, and the widely followed conventions that make it genuinely useful to a human reader, distinct from GitHub's own auto-generated release notes covered in Module 6.

Learning Objectives

  • Explain the purpose of a CHANGELOG.md file and how it differs from GitHub's auto-generated release notes.
  • Structure changelog entries following the Keep a Changelog convention's standard categories.
  • Maintain an 'Unreleased' section for tracking changes ahead of the next actual release.
  • Understand how a changelog can be generated automatically from Conventional Commits history.

Key Terms to Know Before Maintaining a CHANGELOG.md

  • CHANGELOG.md: A file, conventionally at a repository's root, maintaining a structured, human-readable history of notable changes across a project's versions.
  • Keep a Changelog: A widely adopted convention specifying a consistent structure and set of standard categories for changelog entries.
  • Unreleased section: A changelog section tracking notable changes that have already been merged but not yet included in an actual tagged release.
  • Standard categories: Keep a Changelog's defined entry types — Added, Changed, Deprecated, Removed, Fixed, Security.

How to Actually Maintain a Genuinely Useful CHANGELOG.md

A `CHANGELOG.md` file, conventionally placed at a repository's root, maintains a **structured, human-readable history** of a project's notable changes across versions — distinct in purpose from Module 6's GitHub auto-generated release notes, which are tied to and displayed on a specific GitHub Release page. A `CHANGELOG.md` file is a genuine, version-controlled part of the project itself, viewable directly in the repository (and rendered nicely by GitHub, following the same Markdown rendering covered for READMEs in Module 4), giving it a more permanent, centralized, and portable home than release-specific notes tied to one particular hosting platform.

The most widely followed convention for structuring a changelog is **Keep a Changelog**, which specifies a consistent format built around a small set of **standard categories** for each version's entries:

- **Added** — new features.
- **Changed** — changes to existing functionality.
- **Deprecated** — features that still work but are slated for future removal.
- **Removed** — features that have now actually been removed.
- **Fixed** — bug fixes.
- **Security** — specifically security-related fixes, called out separately given their particular importance to a reader.

A well-maintained changelog also keeps an explicit **`[Unreleased]`** section at the very top, above the most recent actual version entry, tracking notable changes that have already been merged into the main branch but haven't yet been included in a formally tagged, actual release — giving anyone watching the project's development visibility into what's coming next, before it officially ships.

A typical structured entry:

```
## [2.5.0] - 2026-06-15

### Added
- Dark mode support for the settings page.

### Fixed
- Corrected rounding error in bulk discount calculations.

## [Unreleased]

### Added
- Work-in-progress support for saved payment methods (not yet released).
```

Directly connecting to the previous two lessons: a well-maintained changelog following this structure can be either maintained **manually** (a developer explicitly adds an entry as part of their pull request, a common team convention) or **fully automatically generated** by tooling like `semantic-release`, which parses Conventional Commits history and maps each commit's type directly onto Keep a Changelog's categories — a `feat:` commit becomes an 'Added' entry, a `fix:` commit becomes a 'Fixed' entry, and so on — producing a consistently structured `CHANGELOG.md` with zero manual writing required, completing the fully automated release pipeline these three lessons have built up together.

CHANGELOG.md Structure: Visual Walkthrough

Draw a mockup of a rendered CHANGELOG.md file, top to bottom: '## [Unreleased]' section with a small 'Added' subheading listing one in-progress item. Below it, '## [2.5.0] - 2026-06-15' with subheadings 'Added' (one entry: 'Dark mode support'), 'Fixed' (one entry: 'Corrected rounding error'). Below that, '## [2.4.1] - 2026-05-02' with just a 'Fixed' subheading. Draw a side arrow from a stack of Conventional Commits ('feat: ...', 'fix: ...') labeled 'Automated tooling parses commit types' pointing directly into the rendered changelog's category subheadings, captioned 'feat: → Added, fix: → Fixed — automatically generated, or written manually following the same structure.'

Keep a Changelog Categories: Quick Reference Table

Keep a Changelog CategoryUsed ForCorresponding Conventional Commits Type
AddedNew featuresfeat:
FixedBug fixesfix:
ChangedChanges to existing functionalityfeat: or refactor: (context-dependent)
Deprecated / RemovedFeatures slated for or actually removedOften paired with a BREAKING CHANGE
SecuritySecurity-specific fixesfix: (flagged as security-relevant)

CHANGELOG.md: Example Structure

# Example CHANGELOG.md structure, following Keep a Changelog

# Changelog

All notable changes to this project will be documented in this file.

## [Unreleased]

### Added
- Work-in-progress support for saved payment methods.

## [2.5.0] - 2026-06-15

### Added
- Dark mode support for the settings page.

### Fixed
- Corrected rounding error in bulk discount calculations.

## [2.4.1] - 2026-05-02

### Fixed
- Resolved crash when submitting an empty checkout form.

## [2.4.0] - 2026-04-20

### Added
- Initial checkout discount feature.

Breaking Down the CHANGELOG.md Example

This example demonstrates the complete Keep a Changelog structure: an `[Unreleased]` section at the top tracking work already merged but not yet formally released, followed by each actual version's entries in reverse-chronological order (most recent first), each organized under standard category subheadings like `Added` and `Fixed`. This exact structure could be maintained by hand — a developer adding an entry as part of their pull request — or generated entirely automatically by parsing Conventional Commits history (previous lesson), mapping each commit's type directly onto the corresponding category, producing this same output with no manual writing required.

How CHANGELOG.md Is Used on Real Open-Source Projects

  • Keep a Changelog is one of the most widely adopted conventions across open-source projects specifically for structuring a CHANGELOG.md file, referenced extensively in project documentation and tooling.
  • Many companies require a changelog entry as part of a pull request's review checklist, treating updating CHANGELOG.md as a routine, expected part of shipping any user-facing change, similar to how Module 5 covered PR description templates.
  • Tools like semantic-release and conventional-changelog automatically generate and maintain a CHANGELOG.md file directly from Conventional Commits history, entirely removing the manual changelog-writing step from a team's release process.
  • Users evaluating whether to upgrade a dependency frequently check its CHANGELOG.md first, specifically looking for Breaking or Removed entries that might affect their own code, directly relying on this exact structured, categorized format.

CHANGELOG.md Interview Questions and Answers

Q1. What is the purpose of a CHANGELOG.md file, and how does it differ from GitHub's auto-generated release notes?

A CHANGELOG.md maintains a structured, human-readable history of a project's notable changes across all versions, as a genuine, version-controlled part of the repository itself. GitHub's auto-generated release notes (Module 6) are tied to and displayed on a specific GitHub Release page, whereas CHANGELOG.md is a more permanent, portable, centralized artifact viewable directly in the repository regardless of hosting platform.

Q2. What are the standard categories defined by the Keep a Changelog convention?

Added (new features), Changed (changes to existing functionality), Deprecated (features slated for future removal), Removed (features actually removed), Fixed (bug fixes), and Security (security-specific fixes, called out separately given their particular importance).

Q3. How can a CHANGELOG.md be automatically generated, and what makes this possible?

Tooling like semantic-release can parse Conventional Commits history (from the previous lesson) and map each commit's type directly onto Keep a Changelog's categories — a feat: commit becomes an Added entry, a fix: commit becomes a Fixed entry — producing a consistently structured changelog with no manual writing required, provided the team consistently follows the Conventional Commits format.

CHANGELOG.md Quiz: Test Your Understanding

1. What is the purpose of the [Unreleased] section in a Keep a Changelog-style CHANGELOG.md?

  1. To list features planned for a distant future version
  2. To track notable changes already merged but not yet included in an actual tagged release
  3. To document deprecated features only
  4. To list every past release ever made

Answer: B. To track notable changes already merged but not yet included in an actual tagged release

Explanation: The Unreleased section specifically tracks changes that have already landed in the main branch but haven't yet been part of a formally tagged, actual release, giving visibility into what's coming next.

2. Which Keep a Changelog category would a fix: Conventional Commit typically map to?

  1. Added
  2. Fixed
  3. Deprecated
  4. Security (always)

Answer: B. Fixed

Explanation: A fix: commit represents a bug fix, which corresponds directly to Keep a Changelog's 'Fixed' category when automatically generating a changelog from Conventional Commits history.

3. How does a CHANGELOG.md differ from GitHub's auto-generated release notes?

  1. They are exactly the same thing
  2. CHANGELOG.md is a version-controlled file within the repository itself, while GitHub's release notes are tied to a specific Release page on that platform
  3. CHANGELOG.md can only be created manually, never automated
  4. GitHub's release notes replace the need for any changelog file

Answer: B. CHANGELOG.md is a version-controlled file within the repository itself, while GitHub's release notes are tied to a specific Release page on that platform

Explanation: CHANGELOG.md is a genuine, portable, version-controlled part of the project's own history, distinct from platform-specific release notes tied to a particular GitHub Release.

Common Mistakes When Maintaining a CHANGELOG.md

  • Never maintaining a CHANGELOG.md at all, relying solely on GitHub's release notes, which are tied to that specific platform rather than being a portable, version-controlled artifact.
  • Not maintaining an Unreleased section, leaving users with no visibility into what's already been merged but not yet formally released.
  • Writing overly technical, commit-message-style changelog entries rather than clear, user-facing descriptions of what actually changed from a reader's perspective.
  • Manually maintaining a changelog inconsistently across a team without a clear process, when automated generation from Conventional Commits could eliminate this inconsistency entirely.

CHANGELOG.md: Exam-Ready Quick Notes

  • CHANGELOG.md: version-controlled, human-readable history of notable changes, distinct from platform-specific GitHub release notes.
  • Keep a Changelog categories: Added, Changed, Deprecated, Removed, Fixed, Security.
  • [Unreleased] section: tracks merged-but-not-yet-released changes, kept at the top.
  • Can be maintained manually or fully automatically generated from Conventional Commits history.

CHANGELOG.md: Key Takeaways

  • CHANGELOG.md is a genuine, portable, version-controlled artifact distinct from platform-specific release notes, worth maintaining even alongside GitHub Releases.
  • The Keep a Changelog convention's standard categories provide a consistent, scannable structure that readers across many different projects can quickly recognize and navigate.
  • This lesson completes the fully automated release pipeline this module has built up: Conventional Commits determine the SemVer bump, and that same commit history can also automatically generate a structured changelog.

Frequently Asked Questions About CHANGELOG.md

Q1. What is a CHANGELOG.md file used for?

It maintains a structured, human-readable history of a project's notable changes across all its versions, kept as a version-controlled file directly within the repository itself, distinct from any specific hosting platform's release notes.

Q2. What is the Keep a Changelog convention?

It's a widely adopted convention specifying a consistent structure for changelog entries, organized under standard categories: Added, Changed, Deprecated, Removed, Fixed, and Security.

Q3. What is the [Unreleased] section in a changelog for?

It tracks notable changes that have already been merged into the project's main branch but haven't yet been included in a formally tagged, actual release, giving visibility into what's coming next before it officially ships.

Q4. Can I automatically generate my CHANGELOG.md instead of writing it by hand?

Yes. If your team consistently follows the Conventional Commits format, tooling like semantic-release can parse that commit history and automatically map each commit's type onto the corresponding Keep a Changelog category, producing a consistently structured changelog with no manual writing required.

Q5. How is CHANGELOG.md different from GitHub's Release notes?

CHANGELOG.md is a genuine, version-controlled file living directly within the repository, portable and viewable regardless of hosting platform. GitHub's auto-generated release notes are tied specifically to a GitHub Release page, which is a platform-specific feature rather than a portable part of the project's own files.

Summary

`CHANGELOG.md`, conventionally at a repository's root, maintains a structured, human-readable history of a project's notable changes across versions — a genuine, portable, version-controlled part of the project itself, distinct from Module 6's GitHub auto-generated release notes, which are tied to a specific platform's Release page. The widely followed Keep a Changelog convention structures entries under standard categories: Added, Changed, Deprecated, Removed, Fixed, and Security. A well-maintained changelog also keeps an explicit `[Unreleased]` section at the top, tracking notable changes already merged but not yet included in an actual tagged release. This structure can be maintained manually, or — completing the fully automated pipeline this module has built across its previous two lessons — generated entirely automatically by tooling that parses Conventional Commits history, mapping each commit's type directly onto the corresponding Keep a Changelog category (`feat:` becomes 'Added', `fix:` becomes 'Fixed'), producing a consistently structured, genuinely useful changelog with zero manual writing required.

Frequently Asked Questions

It maintains a structured, human-readable history of a project's notable changes across all its versions, kept as a version-controlled file directly within the repository itself, distinct from any specific hosting platform's release notes.

It's a widely adopted convention specifying a consistent structure for changelog entries, organized under standard categories: Added, Changed, Deprecated, Removed, Fixed, and Security.

It tracks notable changes that have already been merged into the project's main branch but haven't yet been included in a formally tagged, actual release, giving visibility into what's coming next before it officially ships.

Yes. If your team consistently follows the Conventional Commits format, tooling like semantic-release can parse that commit history and automatically map each commit's type onto the corresponding Keep a Changelog category, producing a consistently structured changelog with no manual writing required.

CHANGELOG.md is a genuine, version-controlled file living directly within the repository, portable and viewable regardless of hosting platform. GitHub's auto-generated release notes are tied specifically to a GitHub Release page, which is a platform-specific feature rather than a portable part of the project's own files.