Keep a changelog from git commits

Over the past years, on software programming projects where my end users where developers (other than myself or my team), I have tried to follow the advice of this website : keepachangelog(.com)

A changelog is defined by Wikipedia as :

a log or record of all notable changes made to a project. [It] usually includes records of changes such as bug fixes, new features, etc.

It is very simple to add one to a project, and brings a lot of value to its users. You can even consume them as Atom/RSS feeds, with tools like allmychanges.com.

Honestly I haven't tried other standards than keepachangelog.com, but what I like about it is that it's aimed at users.

As a software library or API user, when your are faced with a bug or when you are considering an upgrade to a more recent version, you want to be able to rapidly scroll through a changelog and detect useful bug / security fixes, non backward compatible changes or new useful features.

This simple format standard provides exactly that, with a very simple Markdown structure.

I could not find an image I liked illustrating changelogs under a CC license, so I picked this one which represents a tree but reminds me of git branches - Four Seasons Tree by Aya Mulder CC BY-NC-SA 4.0

The keepachangelog.com website clearly states as its top heading:

Don’t let your friends dump git logs into changelogs.

Which is more or less what I am going to advice you do 😏

I think that by making the changelog contribution part of the necessary steps to make code changes, instead of having to edit a Markdown file separately, you won't risk to forget about it.

I recently used gitchangelog which can be configured very easily to follow keepachangelog.com format:

section_regexps = [
    ('Added', [r'^[aA]dded\s*:.*$']),
    ('Changed', [r'^[cC]hanged\s*:.*$']),
    ('Deprecated', [r'^[dD]eprecated\s*:.*$']),
    ('Removed', [r'^[rR]emoved\s*:.*$']),
    ('Fixed', [r'^[fF]ix(ed)?\s*:.*$']),
    ('Security', [r'^[sS]ecu(rity)?\s*:.*$']),
]

output_engine = mustache(".gitchangelog-keepachangelog.tpl")

publish = FileRegexSubst(
    "CHANGELOG.md",
    r'(?s)(<!-- gitchangelog START -->\n).*(<!-- gitchangelog END -->\n)',
    r"\1\o\2"
)
# CHANGELOG
All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com).

It is generated from the `git` commits whose message starts with
`added:` / `changed:` / `deprecated:` / `removed:` / `fixed:` / `security:`
thanks to [gitchangelog](https://github.com/vaab/gitchangelog) :
`pip install gitchangelog pystache`
`gitchangelog`

You can still use [conventional commit messages](https://www.conventionalcommits.org), starting for example with
`chore:` / `docs:` / `refactor:` / `style:` / `test:`, they just won't be included in this changelog.

<!-- gitchangelog START -->
<!-- gitchangelog END -->

Then you simply execute the gitchangelog command in a pre-commit hook or in your release CI pipeline and voilà !

Now, I am far from an expert on this subject. There are many other standards for changelogs, and other tools to use git commits or pull requests to extract such history.

But I see the following advantages to using gitchangelog:

  • it is easy to introduce to an existing code base, while preserving an existing changelog or ignoring old commits
  • it lets you configure the naming convention you want to use in your commit messages
  • it lets you choose whether or not to ignore commits without the required prefixes.
  • it is written in Python 😉