CI and hooks
Enforce commit rules in GitHub Actions and Husky hooks
better-commit uses the same validation rules everywhere: interactive commits, Git hooks, and CI pipelines all load commit.config.ts and run the same checks as bc check.
GitHub Actions
Validate commits in a pull request or on push to your default branch:
name: Commit messages
on:
pull_request:
push:
branches: [main]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: 26
- run: npm ci
- name: Validate commit messages
run: npx bc check --from origin/main --to HEADfetch-depth: 0 ensures Git can resolve origin/main. Adjust branch names and the --from ref to match your workflow.
For a single commit on push, validate the latest message only:
npx bc checkHusky prepare-commit-msg
Install the interactive commit hook with bc init --hooks:
npm install -D husky @better-commit/cli
npx husky init
bc init --hooksThis writes .husky/prepare-commit-msg:
#!/usr/bin/env sh
# better-commit: interactive commit message for git commit
[ -n "$BETTER_COMMIT_SKIP_HOOK" ] && exit 0
[ "$2" = "merge" ] || [ "$2" = "squash" ] && exit 0
export GIT_EDITOR=cat
exec < /dev/tty > /dev/tty 2>&1 bc commit --hook "$1"When you run git commit, Husky invokes bc commit --hook with Git's message file path. better-commit guides you through type, scope, and subject, writes the message to COMMIT_EDITMSG, and returns control to Git — no nested git commit, no second editor.
You can also run bc or bc commit directly; it sets BETTER_COMMIT_SKIP_HOOK when calling Git so the hook does not run again.
Merge and squash commits skip the hook so Git's auto-generated messages are preserved. Use -q -f with bc init --hooks in non-interactive setups to overwrite an existing hook.
commit-msg validation
To validate the message after it is written but before the commit is finalized, add a commit-msg hook that runs:
bc check --editExample .husky/commit-msg:
#!/usr/bin/env sh
bc check --edit--edit validates the contents of COMMIT_EDITMSG — the same file Git passes to commit-msg hooks. This catches invalid messages from git commit -m or editors that bypass prepare-commit-msg.
Combining hooks
A typical setup:
| Hook | Purpose |
|---|---|
prepare-commit-msg | Run bc commit --hook for interactive message composition |
commit-msg | Run bc check --edit as a final gate |
You can use either hook alone. Teams that prefer manual git commit -m often skip prepare-commit-msg and rely on commit-msg plus CI.
CI vs local hooks
- Hooks give immediate feedback before a commit lands locally.
- CI catches messages from contributors who skip hooks or force-push.
Use both for the strongest enforcement. See Commands for the full bc check reference including --from / --to ranges.