An introduction to git cliff for release management
Learn how to automate your software releases
This article introduces tooling that requires a firm understanding of Semantic Versioning, and Conventional Commits. These were previously explained in my articles on Modern Versioning, and Modern Changelogs.
Git Cliff is a tool by Orhun Parmaksız that allows you to automate changelogs and versions. In it’s simplest form it assumes there is one version-number bearing project in a repository. The set up looks something like this,
# Create new repo dir
git init foo
cd foo
echo readme >README.md
git add README.md
git commit -a -m 'initial commit'
git tag 1.0.0
# Git cliff setup
git-cliff --init
git add cliff.toml
git commit -a -m'ci: added git cliff'
git-cliff --unreleased --bump >CHANGELOG.md
git add CHANGELOG.md
git commit -a -m'chore: git-cliff'
git tag $(git cliff --bumped-version)
Now you have a project configured with git cliff
, and it’s bumped its first version. After you run those commands, you’ll see a two new version published
$ git tag
1.0.0
1.0.1
And the git log
will show your chore commit,
commit a840842e48984fc454b2d673e5bc8d6e94547f3a (HEAD -> main, tag: 1.0.1)
Author: Evan Carroll <me@evancarroll.com>
Date: Mon Mar 10 18:37:50 2025 -0500
chore: git-cliff
While there are lots of ways to use git cliff, I believe the best practice is to have
A separate commit for the files touched by git cliff
Where that separate commit is the tag point for the new version
In order to achieve this, whenever you want to publish a new commit simply run
git-cliff --unreleased --bump --prepend CHANGELOG.md
git add CHANGELOG.md
git commit -a -m'chore: git-cliff'
git tag $(git cliff --bumped-version)
Note: the only thing that changes in these four lines from the above, is the “--prepend”
argument. You can repeat this process for each new commit-cycle
echo "New Code" >> main.rs
git add main.rs
git commit -a -m'feat: added a new pseudo rust feature'
git-cliff --unreleased --bump --prepend CHANGELOG.md
git add CHANGELOG.md
git commit -a -m'chore: git-cliff'
git tag $(git cliff --bumped-version)
And now you’ll see the commit with the new tag 1.1.0
commit 2aeb571078c4ef24022cb5dfba1fbc7eabd6fdfc (HEAD -> main, tag: 1.1.0)
Author: Evan Carroll <me@evancarroll.com>
Date: Mon Mar 10 18:40:43 2025 -0500
chore: git-cliff
Monorepos
I have whole entry on just git cliff and monorepos. I highly suggest it but I’m partial. It felt out of place diving into all that detail here.
Other functionality
In all this code we rely on just the defaults of git cliff, which is rather amazing. It has a slew of other cool features. If you’re entertaining adoption I suggest reading about,
Templating: there is a ton of functionality here. The prebuilt templates are documented in
—init
. However you can create your own — no Rust required!Host integrations (for GitLab, GitHub, and Enterprise)