Every good project should keep a changelog, but how do you easily build and maintain it? In this post I’ll show the approach I’ve been using that’s relatively painless for project maintainers and developers.
If you haven’t read the excellent “Keep a Changelog” website you really should. It describes a file that all projects should have, which has a human-readable list of changes for each release version.
The flow I’ll describe here is what I’ve settled on with the team at From Now On to make it easy for developers to add notes in each pull request (we use the gitflow workflow) and easy for the project maintainer to curate the changelog, so that the product owner knows exactly what is in each release.
The changelog file
In the root of the project repository is a markdown file named
CHANGELOG.md which looks like this:
# Change Log All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). --- ## [Unreleased] ### Added ### Changed ### Deprecated ### Removed ### Fixed ### Security --- ## [5.0.7] 2018-08-31 ### Fixed * Cache pre-warming for the events list now happens correctly after game update. --- ## [5.0.6] 2018-08-29 ### Fixed * The OpenAPI definition for `POST`ing to create a game now points to the correct provider. [Unreleased]: https://bitbucket.org/saibotsivad/demo/branches/compare/develop%0Dmaster [5.0.7]: https://bitbucket.org/saibotsivad/demo/branches/compare/v5.0.7%0Dv5.0.6 [5.0.6]: https://bitbucket.org/saibotsivad/demo/branches/compare/v5.0.6%0Dv5.0.5
If you’ve seen a changelog before, this will probably look very familiar, but I need to point out a couple important things:
- The top “Unreleased” section is a sort of template (described below), and it needs to exist above the numbered release section.
- All sections are seperated with the triple dashes, and there’s more whitespace than the original “Keep a Changelog”. This is mostly to support markdown-to-html conversion in different online viewers.
Making a pull request
As part of the gitflow workflow, a developer will make a pull request with some code changes from a feature branch into the development branch.
In every pull request, the developer is expected to log their changes in the
CHANGELOG.md file, writing the change in a human-readable form. I like to think of the text as client-facing, even if client’s won’t see it, as a way to help me write a better log.
The changes are added near the top of the file, just above the “Unreleased” section, above the triple dashes. For example, the commit should look something like this:
and this project adheres to [Semantic Versioning](http://semver.org/). + + --- + + ## [Unreleased] + + ### Changed + + * When thing X happens, side effect Y also happens. + --- ## [Unreleased]
It’s important that a new “Unreleased” section (surrounded by the triple dashes) is created on each pull request. Doing so, and inserting the section at the top, will elimintate nearly all merge conflicts, so developers aren’t tasked with constantly patching their pull requests just to resolve changelog text–a common complaint.
Over time, if the gap between releases is long, the number of “Unreleased” sections might grow to be long. In these cases, the project maintainer or developer should combine all the unreleased sections into one, and put that block below the “template” section.
Doing this reduces the likelihood of merge conflicts in each step.
Make a release
When the project maintainer or developer creates a new release, they curate the
CHANGELOG.md file as part of the process, combining all the “Unreleased” sections into a single numbered release section.
All changes to the project are now well known, without needing to look at each commit message prior to the release!
Prior to adopting this flow, to create a client-facing record of changes at each release, we would look at the git diff between the development and production branches, and from those changes generate a client-facing changelog entry.
This process could take a developer several hours, depending on how many git commits there were and how well written they were.
After adopting this flow, creating a client-facing document of the release went from several hours to a minute or two, which is a significant savings in developer time!
It does require developers to always add to the changelog for every pull request, but with the flow described there aren’t merge conflicts so there hasn’t been any pushback from the development team.
If you’d like help getting your releases under control, reach out and let me know what your struggles are!