Skip to main content

Changelog format

Release-plz generates the changelog by using git-cliff as a library. By default, release-plz uses the keep a changelog format.

You can customize the changelog format in the [changelog] section of the configuration.

How should I write my commits?​

Release-plz assumes you are using Conventional Commit messages.

The most important prefixes you should have in mind are:

  • fix:: represents bug fixes, and results in a SemVer patch bump.
  • feat:: represents a new feature, and results in a SemVer minor bump.
  • <prefix>!: (e.g. feat!:): represents a breaking change (indicated by the !) and results in a SemVer major bump.

Commits that don't follow the Conventional Commit format result in a SemVer patch bump.

Body template​

A template is a text where variables and expressions get replaced with values when it is rendered. By providing a custom body template, you can customize the changelog format.


git-cliff uses the Tera template engine.

See the Tera Documentation for more information about control structures, built-in filters, etc.

Custom built-in filters that git-cliff uses:

  • upper_first: Converts the first character of a string to uppercase.


The context contains the data used to render the template. In the following, we represent the context used for the changelog generation using JSON.

For a conventional commit like:

<type>[scope]: <description>



you can use the following context in the template:

"version": "0.1.0",
"package": "my_crate",
"commits": [
"id": "e795460c9bb7275294d1fa53a9d73258fb51eb10",
"group": "<type> (overridden by commit_parsers)",
"scope": "[scope]",
"message": "<description>",
"body": "[body]",
"footers": [
"token": "<name of the footer, such as 'Signed-off-by'>",
"separator": "<the separator between the token and value, such as ':'>",
"value": "<the value following the separator",
"breaking": false
"breaking_description": "<description>",
"breaking": false,
"conventional": true,
"merge_commit": false,
"links": [
{ "text": "(set by link_parsers)", "href": "(set by link_parsers)" }
"author": {
"name": "User Name",
"email": "",
"timestamp": 1660330071
"committer": {
"name": "User Name",
"email": "",
"timestamp": 1660330071
"commit_id": "a440c6eb26404be4877b7e3ad592bfaa5d4eb210 (release commit)",
"timestamp": 1625169301,
"previous": {
"version": "previous release"


A conventional commit's body may end with any number of structured key-value pairs known as footers.

They follow a format similar to the git trailers convention:


You can access the footers in the template using the commit.footers array. Each object in the array has the following fields:

  • token, the name of the footer (preceding the separator character)
  • separator, the footer's separator string (either : or #)
  • value, the value following the separator character
  • breaking, which is true if this is a BREAKING CHANGE: footer, and false otherwise

Here are some examples of footers:

  • Signed-off-by: User Name <>
  • Reviewed-by: User Name <>
  • Fixes #1234
  • BREAKING CHANGE: breaking change description

Breaking Changes​

The breaking flag is set to true when:

  • The commit has an exclamation mark after the commit type and scope, e.g.:

    feat(scope)!: this is a breaking change
  • Or when the BREAKING CHANGE: footer is present:

    feat: add xyz

    BREAKING CHANGE: this is a breaking change

breaking_description contains:

  • The description of the BREAKING CHANGE footer (if present).
  • the commit message otherwise.

If the BREAKING CHANGE: footer is present, the footer is present in commit.footers.

See also the protect_breaking_commits field.

committer vs author​

From the Git docs:

You may be wondering what the difference is between author and committer. The author is the person who originally wrote the work, whereas the committer is the person who last applied the work. So, if you send in a patch to a project and one of the core members applies the patch, both of you get credit — you as the author, and the core member as the committer.


Here you can find some examples of custom git-cliff templates. Converting the git-cliff configuration file into the [changelog] section of the release-plz configuration file is easy.

If you want to contribute your cool template using the release-plz configuration file, please open a PR! πŸ™

Tips and tricks​

Discard duplicate commits​

{% for commit in commits | unique(attribute="message") %}

Filter merge commits​

{% for group, commits in commits | filter(attribute="merge_commit", value=false) %}