Skip to main content

Opinionated conventional commit message linter with imperative mood detection

Project description

commit-guard

Opinionated conventional commit message linter with imperative mood detection.

Unlike regular expression only tools, commit-guard uses NLP (nltk POS tagging) to verify that commit descriptions start with an imperative verb.

Example

$ commit-guard
✗ subject does not match 'type(scope): description':
  Merge pull request #5 from fix/branch missing 'Signed-off-by' trailer
✗ commit is not signed (GPG/SSH)

Installation

From PyPI:

uv tool install git-commit-guard

or:

pipx install git-commit-guard

From a local clone:

uv tool install -e .

During development:

uv run commit-guard

Usage

# check HEAD
commit-guard

# check specific commit
commit-guard abc1234

# check commit message file (for git hooks)
commit-guard --message-file .git/COMMIT_EDITMSG

# pipe message via stdin
echo "fix(auth): add token refresh" | commit-guard

Selecting checks

All checks run by default. Use --enable or --disable with comma-separated values:

# only check subject format and imperative mood
commit-guard --enable subject,imperative

# skip body and signature checks
commit-guard --disable body,signed-off,signature

Available checks:

  • subject - Format matches type(scope): description, valid type, lowercase start, no trailing period, max 72 chars
  • imperative - First word is an imperative verb (for example add not added)
  • body - Body is present after a blank line
  • signed-off - Signed-off-by: trailer exists
  • signature - Verify GPG or SSH signature

Subject length

The default maximum subject line length is 72 characters. Override with --max-subject-length:

commit-guard --max-subject-length 100

Type validation

By default the standard conventional commit types are accepted. Use --types to replace the allowed set entirely:

# restrict to a subset
commit-guard --types feat,fix,chore

# add a project-specific type
commit-guard --types feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert,wip

Scope validation

By default any scope is accepted and scope is optional. Use --scopes to restrict allowed values and --require-scope to enforce that a scope is always present:

# only allow known scopes
commit-guard --scopes auth,api,db

# require a scope
commit-guard --require-scope

# combine both
commit-guard --scopes auth,api --require-scope

Configuration file

Place .commit-guard.toml in your project root (or any parent directory) to set defaults for enable, disable, scopes, require-scope, types, and max-subject-length. commit-guard searches upward from the working directory and uses the first file found.

# .commit-guard.toml
disable = ["signature", "body"]
scopes = ["auth", "api", "db"]
require-scope = true
types = ["feat", "fix", "chore", "wip"]
max-subject-length = 100
# .commit-guard.toml
enable = ["subject", "imperative"]

CLI flags (--enable, --disable, --scopes, --require-scope, --types, --max-subject-length) take full precedence and ignore config file values when provided.

Checking a range of commits

# all non-merge commits between tags
git rev-list --no-merges v1.0..v2.0 | while read -r rev; do
    commit-guard "$rev" || git log -1 --oneline "$rev"
done

# only subject checks on a PR range
git rev-list --no-merges origin/main..HEAD | while read -r rev; do
    commit-guard "$rev" --enable subject,imperative
done

pre-commit

Add to your .pre-commit-config.yaml:

---
repos:
  - repo: https://github.com/benner/commit-guard
    rev: v0.1.0
    hooks:
      - id: commit-guard
      - id: commit-guard-signature

Install the hooks:

pre-commit install --hook-type commit-msg --hook-type post-commit

commit-guard runs at the commit-msg stage and checks message format. commit-guard-signature runs at the post-commit stage and verifies the GPG/SSH signature after the commit object is created.

To selectively enable or disable checks, pass args:

      - id: commit-guard
        args: ["--enable", "subject,imperative"]

Imperative mood detection

commit-guard combines two strategies to detect non-imperative descriptions:

  1. nltk POS tagging — flags words tagged as past tense (VBD), gerund (VBG), third person (VBZ), etc.
  2. WordNet morphology as a fallback for words the tagger misclassifies.

This catches common mistakes like added logging or fixes bug while keeping false positives low.

Conventional commit format

type(scope): description

body

trailers

Default types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert. Override with --types or the types config key.

Scope is optional. Mark breaking changes with ! before the colon.

License

GPLv2

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

git_commit_guard-0.9.0.tar.gz (68.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

git_commit_guard-0.9.0-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

Details for the file git_commit_guard-0.9.0.tar.gz.

File metadata

  • Download URL: git_commit_guard-0.9.0.tar.gz
  • Upload date:
  • Size: 68.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for git_commit_guard-0.9.0.tar.gz
Algorithm Hash digest
SHA256 a95993fbbb8e51689b484560f1f6296dcc02e319320af14052503890b53fd31c
MD5 2600ae55b5a6bc320ddebf367e9a734d
BLAKE2b-256 e9c33d362eee37a0ad0ab3f9dcbc82e741341f1efa73aeaf00e632e070e459bc

See more details on using hashes here.

File details

Details for the file git_commit_guard-0.9.0-py3-none-any.whl.

File metadata

  • Download URL: git_commit_guard-0.9.0-py3-none-any.whl
  • Upload date:
  • Size: 14.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for git_commit_guard-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36fb2f521f661aa1e51930232eeca17417bfe558d2a8b7446cc9304f4f87c4dd
MD5 801e65d2fb232c19dd9bf072cecc4db5
BLAKE2b-256 5a577966edd8f0b62437efe16bace1b15035272828d2176761b78204681acb2f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page