gitsnitch 🗡️🦆

Lints your Git commit history against a declarative ruleset — locally as a pre-commit/pre-push hook, or in any CI/CD pipeline.
Think of it as a linter, but for commit hygiene — enforced consistently across every author and every environment.
Installation
Homebrew (macOS / Linux)
cargo-binstall
NuGet / Chocolatey (Windows)
choco install iilei.gitsnitch
Or via dotnet:
Verifying release signatures
All release binaries are GPG-signed. The .sig file covers the extracted binary, not the archive.
Archive names use a friendly OS-arch scheme; signature names use the Rust target triple.
macOS / Linux
|
# example: Linux x86_64
Windows (PowerShell, requires Gpg4win or Git for Windows)
Invoke-WebRequest https://iilei.github.io/pubkey-0F50EA12D4E2AB1D.asc -OutFile pubkey.asc
gpg --import pubkey.asc
# example: Windows x86_64
Expand-Archive gitsnitch-Windows-msvc-x86_64.zip -DestinationPath .
gpg --verify gitsnitch-x86_64-pc-windows-msvc.sig gitsnitch.exe
Public key fingerprint: E298 44DB 66D4 7846 A802 81D6 0F50 EA12 D4E2 AB1D
Quick Start
For developers (local linting)
Lint a single commit while iterating:
With a preset bundle (e.g., enforce conventional commits):
For CI/CD pipelines
Lint a range of commits in a pull request:
Or lint via commit SHA with JSON output:
Built-in Presets
Apply assertion bundles with --preset flags (repeatable):
conventional-commits— enforce Conventional Commitstitle-body-separator— require blank line between title and bodyforbid-wip— block WIP/DO NOT MERGE patternssecurity-related-edits-mention— require explicit mention of security in certain commit types
Examples:
Core Features
- Message rules — regex patterns on commit title, body, or full message
- Diff rules — restrict file paths, detect forbidden line patterns, enforce line-count thresholds
- Context-aware skipping — skip rules conditionally (e.g., on maintenance branches)
- Severity bands — map severity 0–250 to
Information,Warning,Error,Fatal - Exit code mapping — optionally map violation severity to exit code for CI automation
- Shallow clone healing — auto-deepen shallow CI checkouts
- Remediation hints — customizable Jinja2 banner templates per rule
- Config autodiscovery — find
.gitsnitch.toml,.gitsnitchrc,.gitsnitch.json, etc., automatically
Presets provide assertion bundles (with optional assertion-level banner and hint templates) selected at runtime via CLI only.
Rules:
- Presets contain assertions only — no root-level
history,severity_bands, or global switches - Embedded at build-time from snake_case files
- Runtime names use dash-case (e.g.,
conventional-commits) - Selected presets append to config assertions
- Assertion aliases must be globally unique; duplicates fail as a config error
Authoring custom presets:
Use the embedded preset files as templates:
- src/presets_data/conventional_commits.toml
- src/presets_data/title_body_separator.toml
- src/presets_data/forbid_wip.toml
- src/presets_data/security_related_edits_mention.toml
Copy and adapt assertion blocks into your shared config file for project-local customization.
Choosing a lint scope
gitsnitch requires exactly one mode:
--commit-sha <sha>— lint a single commit--source-ref <ref> --target-ref <ref>— lint a range between two refs
These are mutually exclusive. If neither is provided, gitsnitch fails with an explicit error.
Config file autodiscovery
If no --config flag is given, gitsnitch searches the git repository root for config files in this order:
.gitsnitch.toml.gitsnitchrc(TOML format, no extension).gitsnitch.json.gitsnitch.json5.gitsnitch.yaml.gitsnitch.yml
The first match wins. If none is found, gitsnitch runs with no config (no assertions).
Explicit config path:
Read from stdin:
|
Config discovery root
By default, discovery searches the git repository root. Override it with:
GITSNITCH_CONFIG_ROOT=/path/to/config/dir
Or via flag:
# now reads CI_CONFIG_ROOT instead of GITSNITCH_CONFIG_ROOT
Custom namespace:
# reads GITSNITCH_CUSTOM_NAMESPACE_CONFIG_ROOT, etc.
precedence (CLI → env vars → config → defaults)
- CLI flags (highest priority)
- Environment variables (supported runtime keys only)
- Config file values
- Built-in defaults
Supported environment variables
Canonical keys (default prefix GITSNITCH_):
GITSNITCH_CONFIG_ROOT— where to search for config fileGITSNITCH_COMMIT_SHA— commit to lintGITSNITCH_SOURCE_REF— source branch (for range linting)GITSNITCH_TARGET_REF— target branch (for range linting)
Change the prefix:
# reads CI_CONFIG_ROOT, CI_COMMIT_SHA, CI_SOURCE_REF, CI_TARGET_REF
Remap to arbitrary env var names:
Remap rules:
- Format:
KEY=ENV_VAR ENV_VARmust be non-empty- A key can only be remapped once
- For a remapped key, only the remapped env var is read (no fallback)
--remap-env-varis mutually exclusive with non-default--env-prefix
Exit code behavior
gitsnitch reserves exit codes 251..255 for internal/runtime failures.
Violation exit behavior is controlled by violation_severity_as_exit_code:
false(default): violations are reported, exit is0true: exit code is the maximum violating assertion severity (0–250)
Examples:
- violations
{100, 200}with modetrue→ exit200 - violations
{0, 0}with modetrue→ exit0 - any violations with mode
false→ exit0
CLI override:
Precedence:
- CLI flag (if provided)
- config
violation_severity_as_exit_code - default
false
Output formats
By default, gitsnitch renders pretty JSON:
Compact single-line JSON:
Human-friendly text:
Decorative terminal text:
Additionally write a JSON artifact to a file (without changing terminal output style):
--gitsnitch-json requires a real file path and does not accept -.
Hint: text-decorative prints ANSI colors only on compatible TTYs.
On Windows terminals, ConEmuANSI=ON can mark compatibility.
Safety overrides still win: NO_COLOR, TERM=dumb, non-TTY stdout, and CLICOLOR=0 disable color.
For machine-readable output, prefer json or json-compact.
When linting a ref range in a shallow checkout, gitsnitch may run git fetch to deepen history.
Requirement:
CI credentials must allow git fetch from origin.
Common setups:
- CI-native checkout token persisted for later fetches
- Git credential helper configured in the runner
- Optional
.netrcfile
Example .netrc:
machine github.com
login x-access-token
password ${GITHUB_TOKEN}
Without credentials, shallow autoheal fetches fail and gitsnitch returns an internal/runtime error (251..255).
Contributing
Code-Quality
One-off run prek (1)
Install pre-commit, pre-push, and post-commit hooks
Configured automation highlights:
pre-push: runs quality/security hooks andmake maintenancepost-commit: runsmake generate-coverage