Conch verifies that your Git commit messages adhere to the Conventional Commits specification. That is, all commit messages must use the following format:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Conventional Commits encourages developers to write better, more descriptive commit messages. It also enables commit messages to be machine-parseable. Use Conch as a Git hook or pull request check to enforce these best practices.
Conch can also inspect your commits and filter them by Conventional Commit attributes like type and scope. Use Conch to prepare changelogs, summarize breaking changes, and automate other CI workflows.
Download Conch from the releases page,
place it somewhere on your path (like /usr/local/bin/
), and ensure the file is executable.
Then, run the program from within your Git repository.
# Validate the ten most recent commits on the current branch
conch 'HEAD~10..'
# Validate all the commits on branch "dev"
conch 'main..dev'
# Validate a specific range of commit hashes
conch '40b9741..2453f95'
The conch
binary is statically linked, so no dependencies are needed.
Conch is available on Docker Hub at csang/conch
:
docker pull csang/conch:0.2
When running the container, bind mount your repository and set it as the container's working directory. (A read-only mount is sufficient.) For example:
docker run --rm -v "$(pwd):/mnt/workspace:ro" --workdir=/mnt/workspace csang/conch:0.2 'HEAD~10..'
Conch can be installed as a commit-msg
hook,
so that it automatically validates your commit messages whenever you perform a git commit
.
We recommend using the pre-commit framework to manage your Git hooks.
Add Conch as a repository-local hook to .pre-commit-config.yaml
.
If you have the standalone version available on your path:
repos:
- repo: local
hooks:
- id: conch-standalone
name: 'Conch: Conventional Commits (standalone version)'
language: system
entry: conch --hook
stages: [commit-msg]
Or, for the Docker version:
repos:
- repo: local
hooks:
- id: conch-docker
name: 'Conch: Conventional Commits (Docker version)'
language: docker_image
entry: csang/conch:0.2 --hook
stages: [commit-msg]
Then, install the hook by running pre-commit install -t commit-msg
.
Usage: conch [options] <revision_range>
conch [-k|--hook] <filename>
-h, --help display this help text
-q, --quiet suppress error messages for bad commits
-v, --verbose verbose log output
-V, --version display version and build info
-c, --config string path to config file
-r, --repo string path to the git repository
-k, --hook run as git commit-msg hook, validating a file (see docs)
-T, --types comma_separated_strings filter commits by type
-S, --scopes comma_separated_strings filter commits by scope
-B, --breaking show breaking changes (e.g., feat!)
-M, --minor show minor changes (e.g., feat)
-P, --patch show patch changes (e.g., fix)
-U, --uncategorized show other changes that are not breaking/minor/patch
-l, --list list matching commits
-f, --format string format matching commits using a Go template
-n, --count show the number of matching commits
-i, --impact show the max impact of the commits (breaking/minor/patch/uncategorized)
-b, --bump-version string bump up the specified version number based on the changes in the range
conch
requires one positional argument specifying the range of commits to parse.
For example:
# Validate the ten most recent commits on the current branch
conch 'HEAD~10..'
# Validate all the commits on branch "dev"
conch 'main..dev'
# Validate a specific range of commit hashes
conch '40b9741..2453f95'
See the Git documentation for more tips on how to specify a commit range.
In most cases, you should run conch
from within your project's working directory,
just as you would run other git
commands. Use the --repo
flag if you need to point
conch
at a different directory. For Docker, you can also set the working directory
as part of the run command, docker run --workdir
.
conch
validates the range of commits and reports any that violate
the Conventional Commits standard.
Add an output option to display more information about the commits that were successfully parsed.
conch -l 'HEAD~5..'
2453f95: fix(post): add runServices to dev container sample code
46597ca: feat: add issue reporting links
647e997: chore(deps): upgrade gems
40d1d41: feat(post): alpine linux
36a3e9d: feat(post): python type annotations
Commits are listed in a human-readable format. Use a format specifier if you need to generate custom machine-readable output.
conch -f '{{ .Id }} {{ .Type }}\n' 'HEAD~5..'
2453f95585b93dc14bb986191e422c31e76171b4 fix
46597ca0f173b7675e4aa26d5fdee30e49be83eb feat
647e99725a12f107f73bb835b185fb73fc19e5d8 chore
40d1d41194a5b9b08945c8778b7a7fc55046c749 feat
36a3e9d2ef0e5157952650f50d2613c5dc079748 feat
The format specifier is a Go template which accepts the following variables:
.Id # The git commit hash
.ShortId # The abbreviated git commit hash
.Type # The commit type
.Scope # The commit scope (may be empty)
.Description # The commit description (may be empty)
.Body # The remainder of the commit message, excluding any footers (may be empty)
.Footers # The footers, as a list of {Token, Separator, Value} objects (may be empty)
.IsBreaking # Boolean indicating whether the commit was marked as a breaking change
You may also use the following escape sequences:
\t
- tab\n
- newline\\
- literal backslash
conch -n 'HEAD~5..'
5
Given the commits in the range, show the highest impact of the changes based on the commit types and any breaking change designations:
breaking
minor
patch
uncategorized
For example, conch -i 'HEAD~5'
returns breaking
if at least one of
the previous five commits contains a breaking change. It returns minor
if there is at least one fix
, and no breaking changes.
Given the specified version number, output the next version number in the sequence based on the impact of the commits in the range. Use this function to help automate tagged releases of your project.
For example, conch -b '1.0.0' 'HEAD~5'
returns 2.0.0
if at least one of
the previous five commits contains a breaking change. It returns 1.1.0
if
there is a fix
or other minor commit in the range, and no breaking changes.
The starting version number must be a semantic version:
major.minor.patch[-prerelease_info][+build_metadata]
1.2.3
1.2.3-alpha.1+build.92690d
Note: Prerelease info and build metadata is always stripped from the output. Major version zero (often used during initial development) is not treated specially.
Use a filter option to control the output.
- Filters do not affect commit validation. All commits in the range are validated against the Conventional Commits specification, regardless of filter options.
- In accordance with the specification, all filters perform case-insensitive
matching, except for
-B
,--breaking
.
conch -T 'feat,fix' 'HEAD~5..'
2453f95: fix(post): add runServices to dev container sample code
46597ca: feat: add issue reporting links
40d1d41: feat(post): alpine linux
36a3e9d: feat(post): python type annotations
conch -S post 'HEAD~5..'
2453f95: fix(post): add runServices to dev container sample code
40d1d41: feat(post): alpine linux
36a3e9d: feat(post): python type annotations
Commits without a scope:
conch -S '' 'HEAD~5..'
46597ca: feat: add issue reporting links
Commits with scope "post", or commits without a scope:
conch -S 'post,' 'HEAD~5..'
2453f95: fix(post): add runServices to dev container sample code
46597ca: feat: add issue reporting links
40d1d41: feat(post): alpine linux
36a3e9d: feat(post): python type annotations
-B
,--breaking
: select commits marked with!
or aBREAKING CHANGE
footer.-M
,--minor
: select minor changes likefeat
-P
,--patch
: select patch changes likefix
-U
,--uncategorized
: select all other commit types
Example: List all patches and other low-impact changes:
conch -P -U 'HEAD~5..'
2453f95: fix(post): add runServices to dev container sample code
647e997: chore(deps): upgrade gems
To customize which commit types are treated as minor and patch, use a conch.yml
configuration file, described later in this document.
A commit matches the filters if the type AND scope are correct, AND the impact of the change matches one of the impact filters.
conch -T fix -S post -M -P -U 'HEAD~5..'
2453f95: fix(post): add runServices to dev container sample code
Conch exits successfully if all commits in the range comply with the Conventional Commits specification. Otherwise, it exits with a non-zero status code.
Conch can enforce custom commit policies. Example scenarios:
- Require a specific set of commit types, scopes, or footers
- Require all commits to specify a scope
- Limit the length of the commit description
- Ignore certain commit message patterns
To customize the behavior of Conch, create a conch.yml
file at the root
of your repository. Use the conch.default.yml
file
as a starting point for your configuration, and see the comments there
explaining the file format.
Note: If you need to put your configuration file somewhere else, you can
select it via -c
or --config
:
conch -c '/alternate/path/to/conch.yml' 'HEAD~5..'
Example run command:
docker-compose run --build --rm app
Available services:
app
- contains the compiled binaries, ready for production deploymentdev
- dev container for running arbitrary build and debug commandstest
- run tests in dev containercover
- run tests with code coverage
Conch is licensed under the MIT license. See LICENSE.txt.
Conch is statically-linked against the following third-party libraries:
- libc (musl) (MIT)
- libgit2 (Linking Exception to GPL v2)
- libhttp_parser (MIT)
- libssh2 (BSD-3)
- libssl (openssl) (Apache 2.0)
- zlib (License)
It references the following standards:
See go.mod or run conch --version
for links to Go module dependencies
where you can view their open source licenses.