Hook Templates and CI
Hook Templates: Sharing Hooks Across Repos
After this page you can point new repos at a shared hooks directory, and you know why CI still has to run on the server.
.git/hooks is local
Cloning does not copy hooks (Git ignores them in the payload on purpose: a clone would otherwise execute someone else’s scripts). Each clone needs its own install step.
core.hooksPath
mkdir -p ~/desk/git-hooks
# put pre-commit, commit-msg, … there, chmod +x
git config --global core.hooksPath ~/desk/git-hooksEvery repo on this Linux user account now runs those hooks. A repo can override with git config core.hooksPath .githooks (a directory inside the project that you do commit).
Project-local, committed:
mkdir -p ~/desk/desk-api/.githooks
# copy scripts, chmod +x, commit them
git config core.hooksPath .githooksNew clones still must run the git config once, or a Makefile / just recipe / bin/install-hooks script. Document that in README.md.
init.templateDir
mkdir -p ~/desk/git-template/hooks
# scripts in that hooks dir
git config --global init.templateDir ~/desk/git-templategit init and git clone copy the template’s hooks/ into the new .git/hooks. Good for your laptop. Teammates need the same config.
CI is the hook you cannot skip
A pre-commit hook is a courtesy. git commit --no-verify and a forge’s web editor skip it. CI on the forge (chapter 32, GitHub Actions in Part VI) runs on the server after push. Put the same checks there: git diff --check, tests, secret scanning.
laptop forge
.git/hooks/pre-commit pre-receive / CI job
│ skippable │ not skippable
▼ ▼
git commit git push accepted
│ │
└──────── git push ────────────┘
Client hooks catch mistakes in milliseconds on Linux. CI is the policy. Use both.
Frameworks
pre-commit.com is a Python manager that installs a tiny .git/hooks/pre-commit and runs a YAML list of linters. Optional. Raw bash hooks in this chapter teach the mechanism; a framework is fine in production if the team already uses it.