feat: add conventional-commits commit-msg hook

This commit is contained in:
2026-07-28 18:49:13 +02:00
commit 5df529ab6e
2 changed files with 61 additions and 0 deletions

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# Client-Side Git Hooks
To use one of these hooks, copy them from the respective directory to `.githooks/` in your repository and name according to the parent directory, then execute
```shell
git config core.hooksPath .githooks
```
It is recommended to then document when you made the copy so you can later propagate upstream changes, eg:
```shell
#!/bin/sh -euC
#
# Reject commit messages that do not conform to Conventional Commits.
#
# Enforces Conventional Commits v1.0.0 at the syntactic level.
# Also enforces a custom list of types.
#
# Upstream: gitea.bp99.eu/bp99/git-hooks
# Updated: 2026-07-15
# [... contents ...]
```
## Tricks
To avoid having to remember the `git` command, add a `Makefile` to your project with a `setup` target:
```makefile
setup:
git config core.hooksPath .githooks
.PHONY: setup
```
Do not forget to communicate to contributors that this `setup` target should be executed after cloning the repo.

View File

@ -0,0 +1,29 @@
#!/bin/sh -euC
#
# Reject commit messages that do not conform to Conventional Commits.
#
# Enforces Conventional Commits v1.0.0 at the syntactic level.
#
# Upstream: gitea.bp99.eu/bp99/git-hooks
subject="$(sed -n 1p "$1")"
second="$(sed -n 2p "$1")"
fail() {
>&2 cat <<EOF
commit-msg: $1
subject: $subject
format: <type>[(<scope>)][!]: <description>
Bypass with: git commit --no-verify
EOF
exit 1
}
# type, optional (scope), optional !, terminal ': ', non-emtpy desc
printf '%s' "$subject" | grep -Eq '^[[:alpha:]]+(\([^()]+\))?!?: .+' \
|| fail 'subject does not conform to Conventional Commits'
# Body must begin one blank line after description
[ -z "$second" ] || fail 'Line 2 must be blank'