Skip to main content
The [git] section contains parsing and git-related configuration options that control how commits are processed and included in the changelog.

Conventional Commits

conventional_commits
boolean
default:"false"
Parse commits according to the Conventional Commits specification.Conventional commits follow this format:
<type>[optional scope]: <description>

[optional body]

[optional footer(s)]
Example:
[git]
conventional_commits = true
filter_unconventional
boolean
default:"false"
Exclude commits that don’t match the conventional commits specification.Example:
[git]
conventional_commits = true
filter_unconventional = true
require_conventional
boolean
default:"false"
Require all commits to be conventional. If any unconventional commits are found, changelog generation fails.Takes precedence over filter_unconventional. Checking occurs after commit_parsers are applied.Example:
[git]
conventional_commits = true
require_conventional = true
split_commits
boolean
default:"false"
Split commits on newlines, treating each line as an individual commit.Note: This violates conventional commits specification.Example:
[git]
split_commits = false

Commit Processing

commit_preprocessors
array
Regex-based preprocessors to modify commit messages before parsing.Each preprocessor has:
  • pattern - Regex pattern to match
  • replace - Replacement string (optional)
  • replace_command - Shell command for replacement (optional)
Examples:
[git]
commit_preprocessors = [
  # Remove PR merge prefix
  { pattern = 'Merged PR #[0-9]: (.*)', replace = "$1" },
  
  # Replace issue numbers with links
  { pattern = '\\(#([0-9]+)\\)', replace = "([#${1}](<REPO>/issues/${1}))" },
  
  # Fix spelling with typos
  { pattern = '.*', replace_command = 'typos --write-changes -' },
  
  # Use git to get full commit message
  { pattern = '.*', replace_command = 'git show -s --format=%B $COMMIT_SHA' },
]
commit_parsers
array
Regex-based parsers for extracting data from commits and assigning them to groups.Each parser can match on:
  • message - Commit message (description)
  • body - Commit body
  • footer - Commit footer
  • sha - Commit SHA
  • field - Any commit field (e.g., author.name)
And can set:
  • group - Group name for the commit
  • scope - Override commit scope
  • default_scope - Default scope if none exists
  • skip - Skip this commit
Examples:
[git]
commit_parsers = [
  # Group by commit type
  { 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|^ci", group = "Miscellaneous Tasks" },
  
  # Skip certain commits
  { message = "^chore\\(release\\): prepare for", skip = true },
  { message = "^chore\\(deps.*\\)", skip = true },
  
  # Match on body
  { body = ".*security", group = "Security" },
  
  # Match on footer
  { footer = "^changelog: ?ignore", skip = true },
  
  # Use scope in group name
  { message = '^fix\\((.*)\\)', group = 'Fix (${1})' },
  
  # Set default scope
  { message = "^doc", group = "Documentation", default_scope = "other" },
  
  # Override scope
  { message = "(www)", scope = "Application" },
  
  # Skip specific commit by SHA
  { sha = "f6f2472bdf0bbb5f9fcaf2d72c1fa9f98f772bb2", skip = true },
  
  # Match on commit field
  { field = "author.name", pattern = "John Doe", group = "John's stuff" },
]
protect_breaking_commits
boolean
default:"false"
Prevent commits with breaking changes from being skipped by commit parsers.Example:
[git]
protect_breaking_commits = true
filter_commits
boolean
default:"false"
Filter out commits that are not matched by any commit parser.Example:
[git]
filter_commits = false
fail_on_unmatched_commit
boolean
default:"false"
Fail with a non-zero exit code if any commit is not matched by commit parsers.Useful to enforce that all commits are classified. Commits explicitly skipped (with skip = true) are not considered unmatched.Example:
[git]
fail_on_unmatched_commit = true

Tag Configuration

tag_pattern
string
Regex pattern for matching git tags that represent releases.Can be overridden with --tag-pattern argument.Example:
[git]
tag_pattern = "v[0-9].*"
skip_tags
string
Regex pattern to skip processing matched tags.Commits from skipped tags are dropped from the changelog.Can be overridden with --skip-tags argument.Example:
[git]
skip_tags = "beta|alpha"
ignore_tags
string
Regex pattern to exclude matched tags after applying tag_pattern.Unlike skip_tags, commits from ignored tags are included in the next tag.Note: If a commit has multiple tags and any tag matches, all associated tags are ignored.Can be overridden with --ignore-tags argument.Example:
[git]
ignore_tags = "rc|v2.1.0|v2.1.1"
count_tags
string
Regex pattern to count only matched tags in the final result.Works like an inverted version of ignore_tags - includes all commits but only counts specific tags.Can be overridden with --count-tags argument.Example:
[git]
count_tags = "v[0-9]+\\.[0-9]+\\.[0-9]+$"
use_branch_tags
boolean
default:"false"
Include only tags that belong to the current branch.Example:
[git]
use_branch_tags = false

Commit Ordering

topo_order
boolean
default:"false"
Process tags in topological order instead of chronological.Can also be set with --topo-order flag.Example:
[git]
topo_order = false
topo_order_commits
boolean
default:"true"
Process commits in topological order instead of chronological.
  • false - Equivalent to git log
  • true - Equivalent to git log --topo-order
Example:
[git]
topo_order_commits = true
sort_commits
string
default:"oldest"
Sort commits within each group/release.Allowed values:
  • oldest - Oldest commits first
  • newest - Newest commits first
Can be overridden with --sort argument.Example:
[git]
sort_commits = "newest"
Extract external references from commits and convert them to URLs.Each link parser has:
  • pattern - Regex pattern to match
  • href - URL template (with capture group substitution)
  • text - Link text template (optional)
Examples:
[git]
link_parsers = [
  # GitHub issues and PRs
  { pattern = "#(\\d+)", href = "https://github.com/orhun/git-cliff/issues/$1" },
  
  # IETF RFCs with custom text
  { pattern = "RFC(\\d+)", text = "ietf-rfc$1", href = "https://datatracker.ietf.org/doc/html/rfc$1" },
]
Extracted links are available in templates via commit.links.

Advanced Options

limit_commits
integer
Limit the total number of commits included in the changelog.Example:
[git]
limit_commits = 100
recurse_submodules
boolean
Read and process commits from submodules (depth 1 only).Submodule commits are available in templates via submodule_commits.Example:
[git]
recurse_submodules = true
include_paths
array
Include only commits that modify files matching these glob patterns.Note: When set, the current working directory is not included by default.Example:
[git]
include_paths = ["src/", "doc/**/*.md"]
exclude_paths
array
Exclude commits that only modify files matching these glob patterns.Takes priority over include_paths:
  • Commits touching both included and excluded paths are included
  • Commits only modifying excluded paths are excluded
Example:
[git]
exclude_paths = ["unrelated/", "*.lock"]

Complete Example

[git]
conventional_commits = true
filter_unconventional = true
require_conventional = false
split_commits = false

commit_preprocessors = [
  { pattern = '\\(#([0-9]+)\\)', replace = "([#${1}](https://github.com/orhun/git-cliff/issues/${1}))" },
  { pattern = '.*', replace_command = 'typos --write-changes -' },
]

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\\(clippy\\)", skip = true },
  { message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
  { message = "^style", group = "<!-- 5 -->🎨 Styling" },
  { message = "^test", group = "<!-- 6 -->🧪 Testing" },
  { message = "^chore\\(release\\): prepare for", skip = true },
  { message = "^chore\\(deps.*\\)", skip = true },
  { message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
  { body = ".*security", group = "<!-- 8 -->🛡️ Security" },
  { message = "^revert", group = "<!-- 9 -->◀️ Revert" },
]

protect_breaking_commits = false
filter_commits = false
fail_on_unmatched_commit = false

tag_pattern = "v[0-9].*"
skip_tags = "beta|alpha"
ignore_tags = "rc"

use_branch_tags = false
topo_order = false
topo_order_commits = true
sort_commits = "newest"

link_parsers = [
  { pattern = "#(\\d+)", href = "https://github.com/orhun/git-cliff/issues/$1" },
]

limit_commits = 1000
recurse_submodules = false
include_paths = ["src/"]
exclude_paths = ["*.lock"]

Build docs developers (and LLMs) love