A pre-commit hook is the cheapest place to enforce commit policy: the developer finds out while they are still writing the message, not after a CI round trip.
Add Commit Check to .pre-commit-config.yaml:
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.20.0
hooks:
- id: check-message
- id: check-branch
- id: check-author-name
- id: check-author-emailThen install the hooks. check-message runs at the commit-msg stage, so it
needs its own install step:
$ pre-commit install --hook-type commit-msg
$ pre-commit installThat is it. The next malformed commit message is rejected before it exists.
!!! warning "If check-message never runs"
It is almost always because `pre-commit install --hook-type commit-msg` was
not run — a plain `pre-commit install` only wires up the `pre-commit` stage.
More in [Troubleshooting](../troubleshoot.md).
| Hook ID | Stage | Rules |
|---|---|---|
check-message |
commit-msg |
CC001–CC016 |
check-branch |
pre-commit |
CC201–CC202 |
check-author-name |
pre-commit |
CC101 |
check-author-email |
pre-commit |
CC102 |
check-no-force-push |
pre-push |
CC301 |
check-files |
pre-push |
CC302–CC304 |
check-tag |
pre-push |
CC401 |
The three pre-push hooks need their own install too:
$ pre-commit install --hook-type pre-pushcheck-tag checks the tags the push sends: the tag a tag push names, and on
a branch push, such as git push --follow-tags, the tags on every commit the
push carries.
pre-commit works out which commits a push carries from your remote-tracking
refs, such as origin/main, and runs no hook for a push that creates a ref
without carrying new commits by that measure. So a new tag pushed on its own,
when the commit it points at is already in a remote-tracking ref, is never seen
by check-tag. The same holds for a tag that git push --follow-tags sends
along with a branch push in that case.
Options can be passed as hook arguments, which keeps everything in one file:
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.20.0
hooks:
- id: check-message
args:
- --subject-imperative=true
- --subject-max-length=72
- --allow-merge-commits=falseA cchk.toml is usually the better choice once you have more than a couple of
options, because CI and the CLI read it too. See
Configuration for the precedence rules.
Give check-message the --fix argument and it corrects a message whose
every failure has a mechanical fix, such as a type written Fix or a missing
colon, and lets the commit through:
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.20.0
hooks:
- id: check-message
args: [--fix]With that, git commit -m "Fix: add streaming support" records
fix: add streaming support. A message that needs a judgment, such as one
with no type at all, is rejected as before. More in
Fixing a message in place.
Occasionally you need to get a commit through — a mid-rebase fixup, an
automated migration. pre-commit supports this natively:
$ SKIP=check-message git commit -m "wip"!!! warning "Local hooks are not a policy boundary"
Anyone can pass `--no-verify`. Hooks exist to give fast feedback to people
who want to follow the policy, not to stop people who don't. Pair them with
the [GitHub Action](github-actions.md), which runs where it cannot be
skipped.