Git Hooks Cheat Sheet

Git hooks automation — client-side and server-side hooks for linting, testing, commit message validation, and deployment triggers.

Last Updated: May 1, 2025

Common Client Hooks

HookWhen It RunsCommon Use
pre-commitBefore commit message editorLint, format, run unit tests
prepare-commit-msgAfter editor, before commitAuto-generate message template
commit-msgAfter message is writtenValidate commit message format
post-commitAfter commit completesNotification, update issue tracker
pre-rebaseBefore rebase startsPrevent rebase of protected branches
post-checkoutAfter checkout/switchSet up project-specific config
post-mergeAfter a successful mergeRun migrations, update dependencies
pre-pushBefore push to remoteRun full test suite, security scan

Hook Examples

#!/bin/sh
Every hook starts with a shebang line
npm run lint
Pre-commit: run linter, reject on failure
npm test
Pre-push: run full test suite before allowing push
grep -qE '^(feat|fix|docs)' $1
Commit-msg: enforce conventional commit format
branch=$(git rev-parse --abbrev-ref HEAD)
Post-checkout: detect current branch
npm install
Post-merge: auto-install new dependencies
git diff --cached --name-only
Pre-commit: list files about to be committed
exec < /dev/tty
Pre-commit: enable interactive prompts in hooks

Setting Up Hooks

chmod +x .git/hooks/pre-commit
Make a hook executable (required!)
cp hooks/pre-commit .git/hooks/
Copy a custom hook into place
nano .git/hooks/commit-msg
Create or edit a hook with any editor
git config core.hooksPath hooks/
Redirect Git to look for hooks in hooks/ dir
ls -la .git/hooks/
List all hooks (sample hooks end in .sample)
cp -r hooks/ .git/hooks/ && chmod +x .git/hooks/*
Bulk install shared hooks

Server-Side Hooks

ItemDescription
pre-receiveRuns on remote before refs are updated — gatekeeper for pushes
updateRuns once per branch being pushed; can reject per-branch
post-receiveRuns after push completes — trigger CI, deploy, notifications
Bare RepositoriesServer hooks only work in bare repos (git init --bare)
Protected BranchesUse pre-receive to block force-push to main/master
Deploy on Pushpost-receive: checkout to web root for simple deployments
Email Notificationspost-receive: send email to team on push
Audit Loggingupdate: log who pushed what to which branch
Pro Tip: Share hooks with your team using a script in the repo that symlinks .git/hooks/ to a tracked hooks/ directory.