A hook is a script Git runs automatically at a specific point in its workflow. If the hook exits non-zero, Git aborts the operation. That's the whole interface — anything you can script can run as a hook.
Hooks live in .git/hooks/. Git ships sample scripts there (pre-commit.sample); rename one without the .sample suffix and make it executable to activate it.
The most-used hooks:
- pre-commit — fires before
git commit. Lint, format, scan for secrets. Reject the commit if anything fails.
- commit-msg — fires after the message is written. Validate the format (e.g. enforce conventional commits).
- pre-push — fires before
git push. Run the test suite to block broken pushes.
- post-merge — fires after
git pull/merge. Re-install dependencies if package.json changed.
.git/hooks/ is not committed, so per-machine setup doesn't share. Portable solutions (Husky for JS, pre-commit for Python, lefthook in any language) keep hooks in a committed folder and wire them via git config core.hooksPath.