Template Examples
This page showcases complete template examples demonstrating different changelog formats. Each example includes the TOML configuration and resulting output.Keep a Changelog
A template following the Keep a Changelog format.Configuration
# examples/keepachangelog.toml
[changelog]
header = """
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
"""
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 | upper_first }}
{% for commit in commits %}
- {{ commit.message | split(pat="\n") | first | upper_first | trim }}
{% endfor %}
{% endfor %}
"""
footer = """
{% for release in releases -%}
{% if release.version -%}
{% if release.previous.version -%}
[{{ release.version | trim_start_matches(pat="v") }}]: \
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}\
/compare/{{ release.previous.version }}..{{ release.version }}
{% endif -%}
{% else -%}
[unreleased]: https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}\
/compare/{{ release.previous.version }}..HEAD
{% endif -%}
{% endfor %}
<!-- generated by git-cliff -->
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = false
commit_parsers = [
{ message = "^[a|A]dd", group = "Added" },
{ message = "^[s|S]upport", group = "Added" },
{ message = "^[r|R]emove", group = "Removed" },
{ message = "^.*: add", group = "Added" },
{ message = "^.*: support", group = "Added" },
{ message = "^.*: remove", group = "Removed" },
{ message = "^.*: delete", group = "Removed" },
{ message = "^test", group = "Fixed" },
{ message = "^fix", group = "Fixed" },
{ message = "^.*: fix", group = "Fixed" },
{ message = "^.*", group = "Changed" },
]
sort_commits = "oldest"
Output
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Support multiple file formats
### Changed
- Use cache while fetching pages
## [1.0.1] - 2021-07-18
### Added
- Add release script
### Changed
- Expose string functions
## [1.0.0] - 2021-07-18
### Added
- Add tested usage example
- Add ability to parse arrays
- Add README.md
### Changed
- Initial commit
### Fixed
- Rename help argument due to conflict
[unreleased]: https://github.com/orhun/git-cliff-readme-example/compare/v1.0.1..HEAD
[1.0.1]: https://github.com/orhun/git-cliff-readme-example/compare/v1.0.0..v1.0.1
<!-- generated by git-cliff -->
Detailed Format
A detailed changelog showing commit IDs and footers.Configuration
# examples/detailed.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 %}\
{% if previous %}\
{% if previous.commit_id and commit_id %}
[{{ previous.commit_id | truncate(length=7, end="") }}]({{ previous.commit_id }})...\
[{{ commit_id | truncate(length=7, end="") }}]({{ commit_id }})
{% endif %}\
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | split(pat="\n") | first | upper_first | trim }} ([{{ commit.id | truncate(length=7, end="") }}]({{ commit.id }}))\
{% if commit.footers %}\
{% for footer in commit.footers -%}
, {{ footer.token }}{{ footer.separator }}{{ footer.value }}\
{% endfor %}\
{% endif %}
{% endfor %}
{% endfor %}
"""
footer = """
<!-- generated by git-cliff -->
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = false
commit_parsers = [
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^doc", group = "Documentation" },
{ message = "^perf", group = "Performance" },
{ message = "^refactor", group = "Refactor" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore|^ci", group = "Miscellaneous Tasks" },
]
sort_commits = "oldest"
Output
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased
### Features
- Support multiple file formats (a9d4050)
- Use cache while fetching pages (df6aef4)
## [1.0.1] - 2021-07-18
ad27b43...06412ac
### Miscellaneous Tasks
- Add release script (06412ac)
### Refactor
- Expose string functions (e4fd3cf)
## [1.0.0] - 2021-07-18
### Bug Fixes
- Rename help argument due to conflict (9add0d4)
### Documentation
- Add README.md (81fbc63)
- Add tested usage example (ad27b43)
### Features
- Add ability to parse arrays (a140cef)
<!-- generated by git-cliff -->
Scoped Commits
Group commits by scope within each type.Configuration
# examples/scoped.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 | upper_first }}
{% for group, commits in commits | group_by(attribute="scope") %}
#### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }}
{% endfor %}
{% endfor %}\
{% endfor %}
"""
footer = """
<!-- generated by git-cliff -->
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = true
commit_parsers = [
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^doc", group = "Documentation", default_scope = "unscoped" },
{ message = "^perf", group = "Performance" },
{ message = "^refactor", group = "Refactor" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore", group = "Miscellaneous Tasks" },
]
sort_commits = "oldest"
Output
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased
### Features
#### Cache
- Use cache while fetching pages
#### Config
- Support multiple file formats
## 1.0.1 - 2021-07-18
### Miscellaneous Tasks
#### Release
- Add release script
### Refactor
#### Parser
- Expose string functions
## 1.0.0 - 2021-07-18
### Bug Fixes
#### Args
- Rename help argument due to conflict
### Documentation
#### Example
- Add tested usage example
#### Project
- Add README.md
### Features
#### Parser
- Add ability to parse arrays
<!-- generated by git-cliff -->
Styled with Emojis and Scopes
The default git-cliff template with emoji icons and inline scopes.Configuration
# cliff.toml (git-cliff default)
[remote.github]
owner = "orhun"
repo = "git-cliff"
[changelog]
header = """
# Changelog
All notable changes to this project will be documented in this file.
"""
body = """
{%- macro remote_url() -%}
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
{%- endmacro -%}
{% macro print_commit(commit) -%}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }} - \
([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))
{% endmacro -%}
{% if version %}\
{% if previous.version %}\
## [{{ version | trim_start_matches(pat="v") }}]\
({{ self::remote_url() }}/compare/{{ previous.version }}..{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% endif %}\
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits
| filter(attribute="scope")
| sort(attribute="scope") %}
{{ self::print_commit(commit=commit) }}
{%- endfor %}
{% for commit in commits %}
{%- if not commit.scope -%}
{{ self::print_commit(commit=commit) }}
{% endif -%}
{% endfor -%}
{% endfor -%}
{%- if github -%}
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
## New Contributors ❤️
{% endif %}\
{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
* @{{ contributor.username }} made their first contribution
{%- if contributor.pr_number %} in \
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
{%- endif %}
{%- endfor -%}
{%- endif %}
"""
footer = """
<!-- generated by git-cliff -->
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = true
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->⛰️ Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
]
sort_commits = "newest"
Output
# Changelog
All notable changes to this project will be documented in this file.
## [unreleased]
### ⛰️ Features
- *(cache)* Use cache while fetching pages - ([df6aef4](https://github.com/orhun/git-cliff/commit/df6aef4))
- *(config)* Support multiple file formats - ([a9d4050](https://github.com/orhun/git-cliff/commit/a9d4050))
## [1.0.1] - 2021-07-18
### 🚜 Refactor
- *(parser)* Expose string functions - ([e4fd3cf](https://github.com/orhun/git-cliff/commit/e4fd3cf))
### ⚙️ Miscellaneous Tasks
- *(release)* Add release script - ([06412ac](https://github.com/orhun/git-cliff/commit/06412ac))
## [1.0.0] - 2021-07-18
### ⛰️ Features
- *(parser)* Add ability to parse arrays - ([a140cef](https://github.com/orhun/git-cliff/commit/a140cef))
### 🐛 Bug Fixes
- *(args)* Rename help argument due to conflict - ([9add0d4](https://github.com/orhun/git-cliff/commit/9add0d4))
### 📚 Documentation
- *(example)* [**breaking**] Add tested usage example - ([ad27b43](https://github.com/orhun/git-cliff/commit/ad27b43))
- *(project)* Add README.md - ([81fbc63](https://github.com/orhun/git-cliff/commit/81fbc63))
<!-- generated by git-cliff -->
Release Statistics
Include commit statistics in each release.Configuration
# examples/statistics.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 | upper_first }}
{% for commit in commits %}
- {{ commit.message | split(pat="\n") | first | upper_first | trim }}
{% endfor %}
{% endfor %}
### Commit Statistics
- {{ statistics.commit_count }} commit(s) contributed to the release.
- {{ statistics.commits_timespan | default(value=0) }} day(s) passed between the first and last commit.
- {{ statistics.conventional_commit_count }} commit(s) parsed as conventional.
- {{ statistics.links | length }} linked issue(s) detected in commits.
{%- if statistics.links | length > 0 %}
{%- for link in statistics.links %}
- [{{ link.text }}]({{ link.href }}) (referenced {{ link.count }} time(s))
{%- endfor %}
{%- endif %}
{%- if statistics.days_passed_since_last_release %}
- {{ statistics.days_passed_since_last_release }} day(s) passed between releases.
{%- endif %}
"""
footer = """
<!-- generated by git-cliff -->
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = false
commit_parsers = [
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^doc", group = "Documentation" },
{ message = "^perf", group = "Performance" },
{ message = "^refactor", group = "Refactor" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Testing" },
{ message = "^chore", group = "Miscellaneous Tasks" },
{ body = ".*security", group = "Security" },
]
sort_commits = "oldest"
Output
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased
### Features
- Support multiple file formats
- Use cache while fetching pages
### Commit Statistics
- 2 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 2 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1430 day(s) passed between releases.
## 1.0.1 - 2021-07-18
### Miscellaneous Tasks
- Add release script
### Refactor
- Expose string functions
### Commit Statistics
- 2 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 2 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
## 1.0.0 - 2021-07-18
### Bug Fixes
- Rename help argument due to conflict
### Documentation
- Add README.md
- Add tested usage example
### Features
- Add ability to parse arrays
### Other (unconventional)
- Initial commit
### Commit Statistics
- 5 commit(s) contributed to the release.
- 4 day(s) passed between the first and last commit.
- 4 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
<!-- generated by git-cliff -->
Key Takeaways
Template Features Demonstrated
- Variable usage -
{{ version }},{{ timestamp }},{{ commit.message }} - Conditionals -
{% if version %}...{% else %}...{% endif %} - Loops -
{% for group, commits in commits | group_by(attribute="group") %} - Filters -
| upper_first,| trim_start_matches,| date(format="...") - Macros -
{% macro print_commit(commit) %}...{% endmacro %} - Nested grouping - Group by type, then by scope
- Statistics - Access commit metrics and metadata
- Remote integration - GitHub URLs and contributor info
Common Patterns
Version header with comparison link:{% if previous.version %}
## [{{ version }}](https://github.com/owner/repo/compare/{{ previous.version }}..{{ version }})
{% else %}
## [{{ version }}]
{% endif %}
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message }}
{% endfor %}
{% endfor %}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}{{ commit.message }}
{{ timestamp | date(format="%Y-%m-%d") }}
More Examples
Explore additional templates in the git-cliff examples directory:- github.toml - GitHub release format
- cocogitto.toml - Cocogitto-style changelog
- minimal.toml - Minimal, compact format
- unconventional.toml - Non-conventional commits
Next Steps
- Syntax - Deep dive into Tera syntax
- Context - Complete variable reference
- Configuration - Changelog configuration options