Skip to main content

git-cliff

A changelog generator that parses conventional commits and produces beautifully formatted CHANGELOG files using customizable Tera templates. Written in Rust. Works with any language ecosystem.

✓ Conventional commits ✓ Tera template engine ✓ GitHub Actions support ✓ Written in Rust

What is git-cliff?

git-cliff is a changelog generator that reads your Git history, parses commit messages following the Conventional Commits specification, and renders a formatted changelog using the Tera templating engine. It is language-agnostic, written in Rust, and configured via a cliff.toml file that lives in your repository root.

Unlike tools such as standard-version that couple changelog generation with version bumping, git-cliff focuses purely on the changelog. This makes it flexible: use it standalone, as part of a release script, or via GitHub Actions to auto-generate release notes when you push a tag.

Key Features

Installation

# macOS (Homebrew)
brew install git-cliff

# Rust / Cargo (any platform)
cargo install git-cliff

# Windows (Scoop)
scoop install git-cliff

# npm (for Node.js projects)
npm install --save-dev git-cliff

# Download binary from GitHub Releases
# https://github.com/orhun/git-cliff/releases

Basic Usage

# Generate full changelog to stdout
git cliff

# Write to CHANGELOG.md
git cliff -o CHANGELOG.md

# Generate only unreleased changes
git cliff --unreleased

# Generate only the latest release's changes
git cliff --latest

# Generate changelog for a tag range
git cliff v1.0.0..v2.0.0

# Tag the current HEAD and generate with that version
git cliff --tag v1.2.3 --unreleased

# Init a default cliff.toml in the current directory
git cliff --init

Example cliff.toml

[changelog]
header = """
# Changelog

All notable changes to this project will be documented in this file.
"""
body = """
{% if version %}\
    ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
    ## [Unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
    ### {{ group | striptags | trim | upper_first }}
    {% for commit in commits %}
        - {% if commit.scope %}*({{ commit.scope }})* {% endif %}{{ commit.message | upper_first }}\
    {% endfor %}
{% endfor %}\
"""
trim = true

[git]
conventional_commits = true
filter_unconventional = true
commit_parsers = [
    { message = "^feat", group = "Features" },
    { message = "^fix", group = "Bug Fixes" },
    { message = "^perf", group = "Performance" },
    { message = "^refactor", group = "Refactoring" },
    { message = "^docs", group = "Documentation" },
    { message = "^chore|^ci|^test", skip = true },
]
filter_commits = true
tag_pattern = "v[0-9].*"

Conventional Commits Quick Reference

Type Changelog section Semver bump Example
featFeaturesMINORfeat(auth): add OAuth2 login
fixBug FixesPATCHfix(api): handle null response
perfPerformancePATCHperf: cache query results
refactorRefactoringPATCHrefactor: extract helper fn
docsDocumentationnonedocs: update README
feat!Breaking ChangesMAJORfeat!: remove legacy endpoint
chore/ci/testSkipped (default)nonechore: bump deps

Use Cases

Pros and Cons

Pros

  • ✓ Language-agnostic (not tied to Node.js ecosystem)
  • ✓ Extremely flexible Tera templates
  • ✓ Fast Rust binary with no runtime dependency
  • ✓ Official GitHub Actions integration
  • ✓ Handles partial changelogs (latest / unreleased / range)
  • ✓ Active maintenance and growing community

Cons

  • ✗ Requires conventional commits discipline from the whole team
  • ✗ Does not bump version numbers (unlike standard-version)
  • ✗ Tera template syntax has a learning curve
  • ✗ Useless on repos with free-form commit messages
  • ✗ cliff.toml setup takes some initial configuration effort

Frequently Asked Questions

What is git-cliff?▼

git-cliff is a changelog generator that parses your Git commit history and produces a formatted CHANGELOG.md (or any format you define). It uses conventional commits (feat:, fix:, perf:, etc.) to categorize changes into sections like Features, Bug Fixes, and Performance. You configure it via a cliff.toml file using the Tera templating engine. It integrates with GitHub Actions for automatic changelog generation on release.

What is the conventional commits format?▼

Conventional Commits is a specification for commit messages that adds semantic meaning. The format is: type(scope): description. Common types are: feat (new feature, triggers MINOR bump), fix (bug fix, triggers PATCH bump), perf (performance improvement), refactor, docs, test, chore, ci. Breaking changes are marked with BREAKING CHANGE in the footer or an exclamation after the type (feat!:), triggering a MAJOR version bump. Tools like git-cliff, semantic-release, and standard-version rely on this format.

How does git-cliff compare to standard-version?▼

standard-version is a Node.js tool that handles both version bumping and changelog generation together. git-cliff is focused solely on changelog generation and is language-agnostic (written in Rust). git-cliff's Tera templating is significantly more flexible than standard-version's templates, letting you produce any format. standard-version is better for projects that want automatic semver bumping tied to changelog generation. git-cliff is better when you want full control over the changelog format or use it in non-Node projects.

How do I use git-cliff templates?▼

git-cliff uses the Tera templating engine (similar to Jinja2). In cliff.toml, the 'body' field is a Tera template that receives commit objects with fields like message, scope, group, author, timestamp, and version. You can use Tera filters (date, upper_first, striptags), conditionals (if version), and loops (for group, commits in commits | group_by). Set 'prepend = CHANGELOG.md' to prepend each new release to an existing file.

Can git-cliff generate changelogs for a specific tag range?▼

Yes. Run 'git cliff v1.0.0..v2.0.0' to generate a changelog for commits between two tags. Run 'git cliff --latest' to generate only the latest release's changes (since the previous tag). Run 'git cliff --unreleased' to generate changes since the last tag. The '--tag' flag lets you specify what version to use in the output when commits are not yet tagged.

Does git-cliff work with GitHub Actions?▼

Yes. git-cliff has an official GitHub Action (orhun/git-cliff-action) that generates your changelog and can commit it, create release notes, or pass the output to the GitHub Releases API. A common pattern is to trigger it on push to a tag: the action generates the changelog, creates a GitHub Release with the notes, and commits CHANGELOG.md if needed.

Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →