2.6 KiB
Git hooks
Status: Current
Owner: <who maintains this>
Last reviewed: <YYYY-MM-DD>
Governs: docs/architecture/githooks/** and the .githooks/ a project installs
Review trigger: A new guard the repository wants run before a commit; any change
to what a commit message must contain.
Three hooks, and the reason they live in the repository rather than in
.git/hooks: that directory is not versioned, so a hook living there protects
exactly one clone on exactly one machine. These are committed, and one command
points git at them.
Install
mkdir -p .githooks
cp docs/architecture/githooks/{pre-commit,commit-msg,post-commit} .githooks/
chmod +x .githooks/*
git config core.hooksPath .githooks
core.hooksPath is per-clone, so every checkout runs that last line once. Say so
in the project README — an uninstalled hook fails silently, which is the same
class of problem the hooks exist to prevent.
What each one does
| Hook | Guard |
|---|---|
pre-commit |
typecheck, then the test suite, when .ts/.tsx is staged |
commit-msg |
refuses a message with no conventional type |
post-commit |
pushes to the remote, so a guarded commit does not sit locally |
Two settings worth making before you rely on them
pre-commit will use a local test database if you tell it where one is.
Set TEST_DB_PORT and TEST_DB_URL together. Leave them unset and the database
suites skip, which is the right default on a machine with no Postgres — but it
means the hook is running a fraction of the suite, so release.sh is
deliberately stricter and refuses rather than warns.
post-commit pushes. That is the intent — the commit that first added a
pre-commit hook to the reference project sat unpushed for a day, guarded and
invisible — but it is a surprise if you were not expecting it. Read it before
installing it on a repository with a protected branch.
It has a second consequence worth knowing about: the push is what the Command
Center reads, so whatever documentation was not in that commit is now behind
the code by one push. That is the mechanical reason docs/WORK_CYCLE.md asks
for doc edits in the same commit as the change rather than in a tidy-up
afterwards — with this hook installed, "I will document it next commit" means
the site has already published the version without it.
Why a hook and not CI
Both. These are the guards that must run before the artifact exists: a hook that fires after a push, or a CI job that fires after a publish, catches the problem once it is already somewhere it cannot be taken back from. CI is the second opinion; this is the one that runs first.