Maintaining a CHANGELOG in our software projects is indispensable and adds professionalism and seriousness to the product.
Often we forget to update our project’s CHANGELOG—either because we consider it a waste of time, because we don’t really know every change involved, or simply because we forget.
A readable, well-organized changelog makes it easy to communicate changes to other developers, users, and team members we collaborate with. Additionally, it speeds up version auditing, reduces deployment errors, improves traceability in high-demand production environments, and builds trust with our code’s consumers.
🎯 Goal
In this post I’ll show how to use the git-cliff tool to automatically generate and maintain a CHANGELOG.md file following the Keep a Changelog standard. We’ll base everything on a commit history formatted with Conventional Commits, which is key for the automation to classify each change correctly.
This way, we’ll end up with a clear, consistent, and always-up-to-date changelog. ✅
💻 Installation & Configuration
🔧 Prerequisites
- Git installed (≥ 2.20)
- A commit history formatted with Conventional Commits
📲 Installation
macOS (Homebrew)
brew install git-cliff
Linux (Linuxbrew or binary)
brew install git-cliff # if you use Linuxbrew
# or:
curl -sSL https://github.com/jackfirth/git-cliff/releases/download/v0.5.1/git-cliff_0.5.1_Linux_x86_64.tar.gz \
| tar xz -C ~/.local/bin
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
Windows (Scoop or binary)
# With Scoop
scoop install git-cliff
# Or download from Releases, unzip and add to %PATH%.
⚙️ Basic Configuration
Create a cliff.toml
file at the root of your project:
[git]
tag_prefix = "v" # Prefix for semantic tags
[output]
file = "CHANGELOG.md"
format = "MD" # Markdown
[sections]
"🚀 Added" = ["feat"]
"🐛 Fixed" = ["fix"]
"🧰 Changed" = ["perf"]
"⚠️ Deprecated" = ["chore(deprecate)"]
"🚫 Removed" = ["feat!", "BREAKING CHANGE"]
"🔒 Security" = ["fix(security)", "security"]
With this configuration, git-cliff will know how to read your commits and where to group them according to the Keep a Changelog conventions.
🛠️ Advanced Configuration
For mature or more complex projects, you may want to align additional commit types or scopes to well-defined sections. git-cliff lets you configure versatile grouping based on commit types and scopes:
[sections]
"🚀 Features" = ["feat"]
"🐛 Bug Fixes" = ["fix"]
"🧰 Improvements" = ["improvement", "perf"]
"💄 Style" = ["style"]
"📝 Docs" = ["docs"]
"⚠️ Deprecated" = ["chore(deprecate)", "feat(deprecate)"]
"🚫 Removed" = ["feat!", "BREAKING CHANGE"]
"🔒 Security" = ["fix(security)", "security"]
- improvement: small refinements instead of new features
- style: formatting or linting changes
- docs: anything related to documentation
If you need to add more sections, simply extend the [sections]
table with the keys and list of types or scopes your team uses.
🏷️ Generating the CHANGELOG by Version
- Create a tag for the new version in your repository:
git tag v1.3.0
git push origin --tags
- Generate the changelog from the last two version tags:
git cliff v1.2.0..v1.3.0
Or, if you don’t specify tags, it will use the automatic range since the last tag:
git cliff
- Review and commit the updated changelog:
git add CHANGELOG.md
git commit -m "chore: release v1.3.0"
git push origin main
🤖 CI/CD Automation
Automating tedious tasks in your workflow saves a ton of time you can spend on higher-value activities. Automatically generating your changelog is no exception.
⚙️ GitHub Actions
name: 📦 Release
on:
workflow_dispatch:
inputs:
version:
description: 'New version (e.g. 1.3.0)'
required: true
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install git-cliff
run: |
curl -sSL https://github.com/jackfirth/git-cliff/releases/download/v0.5.1/git-cliff_0.5.1_Linux_x86_64.tar.gz \
| tar xz -C ~/.local/bin
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Generate CHANGELOG and tag
env:
VERSION: ${{ github.event.inputs.version }}
run: |
git config user.name "CI Bot 🤖"
git config user.email "[email protected]"
git tag v${VERSION}
git cliff
git add CHANGELOG.md
git commit -m "chore: release v${VERSION}"
git push origin main --tags
🐙 GitLab CI/CD
stages:
- release
release:
stage: release
image: alpine:latest
before_script:
- apk add --no-cache curl git
- curl -sSL https://github.com/jackfirth/git-cliff/releases/download/v0.5.1/git-cliff_0.5.1_Linux_x86_64.tar.gz \
| tar xz -C /usr/local/bin
script:
- git tag v$CI_COMMIT_REF_NAME
- git cliff
- git add CHANGELOG.md
- git commit -m "chore: release v$CI_COMMIT_REF_NAME"
- git push origin HEAD:main --tags
only:
- tags
Conclusions
As a software engineer, I’ve seen projects with neglected change traceability: undocumented versions, teams lost among branches, and unplanned deployments—both in the companies I’ve worked for and in my own side projects.
While automatic changelog generation is a powerful, versatile tool, its effectiveness depends on the team adopting and respecting commit standards—hence the importance of Conventional Commits.
With git-cliff and Keep a Changelog, you gain:
- Reliable automation: your changelog reflects exactly the commits in your repo
- Standardization: all changes classified and formatted consistently
- Professionalism: each release ships with a clear, audited document
Integrate this flow into your project and CI/CD, and you’ll discover that maintaining an impeccable change history is not only simple, but adds immense value to your software’s quality and trustworthiness.
Until next time!
Top comments (0)