Git Hooks — Automate with Every Git Action
AdvancedGit hooks are shell scripts that run automatically at key points in the Git workflow — before commits, before pushes, after merges. They enforce code quality, run tests, and prevent bad commits from ever entering the repository.
Overview
Hooks live in .git/hooks/ and are executable scripts (bash, Python, Node.js — anything with a shebang line). Client-side hooks (pre-commit, commit-msg, pre-push) run on your machine. Server-side hooks (pre-receive, post-receive) run on the remote and can reject pushes. Since .git/ is not committed, hooks are not automatically shared — use tools like Husky (Node) or pre-commit (Python) to version and distribute them. Hooks are the foundation of quality gates: lint, test, format, secrets scanning before any code reaches the remote.
Most Useful Client-Side Hooks
Four hooks cover the majority of automation needs: pre-commit (lint/test), commit-msg (validate message format), post-commit (notifications), and pre-push (run full test suite).
# Hooks live in .git/hooks/
ls .git/hooks/
# pre-commit.sample commit-msg.sample pre-push.sample
# Make a hook executable by removing .sample and adding a shebang
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
# Run ESLint on staged JS files before every commit
staged=$(git diff --cached --name-only --diff-filter=ACM | grep '.js$')
if [ -n "$staged" ]; then
echo "$staged" | xargs npx eslint
if [ $? -ne 0 ]; then
echo "ESLint failed — commit rejected"
exit 1 # Non-zero exit rejects the commit
fi
fi
EOF
chmod +x .git/hooks/pre-commitEnforcing Commit Message Format
The commit-msg hook receives the commit message file as $1. Use it to enforce Conventional Commits or ticket number prefixes.
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/sh
# Enforce Conventional Commits format:
# feat|fix|docs|refactor|test|chore: subject
commit_regex='^(feat|fix|docs|style|refactor|test|chore|ci)((.+))?: .{1,72}'
commit_msg=$(cat "$1")
if ! echo "$commit_msg" | grep -qE "$commit_regex"; then
echo "ERROR: Commit message must follow Conventional Commits:"
echo " feat: add login validation"
echo " fix(auth): handle null email"
echo " docs: update API docs"
exit 1
fi
EOF
chmod +x .git/hooks/commit-msg
# ── Using Husky (share hooks via npm) ────────────────────
npm install --save-dev husky
npx husky init
# .husky/pre-commit
npm run lint
npm run test:unit
# .husky/commit-msg
npx --no -- commitlint --edit $1pre-push and Server-Side Hooks
pre-push runs before git push — use it for full test suites (they are too slow for pre-commit). Server-side pre-receive can reject pushes that don't meet team standards.
# .husky/pre-push — run full tests before pushing
#!/bin/sh
echo "Running full test suite before push..."
npm test
if [ $? -ne 0 ]; then
echo "Tests failed — push rejected"
exit 1
fi
# ── Server-side hooks (on the Git server / GitHub Actions) ──
# pre-receive: runs on remote before accepting push
# Useful for: blocking force-pushes to main,
# enforcing signed commits, branch naming rules
# post-receive: runs after accepting push
# Useful for: triggering CI/CD, sending Slack notifications
# In practice, most teams use:
# - Husky for client-side hooks (pre-commit, commit-msg, pre-push)
# - GitHub/GitLab branch protection rules for server-side enforcement
# - GitHub Actions / CI for test enforcement on PRsKey Points to Remember
- 1Hooks live in .git/hooks/ — any executable script (bash, node, python) triggered by Git events
- 2pre-commit: runs before commit — ideal for linting staged files; non-zero exit rejects the commit
- 3commit-msg: validates commit message format — receives the message file as $1
- 4pre-push: runs before pushing — use for full test suites (too slow for pre-commit)
- 5Use Husky (Node) or pre-commit framework (Python) to version and share hooks with your team
Interview Questions
Sign in to ask AriaWhat are Git hooks? Give three examples of how you would use them.
How do you share Git hooks with your team? Why can't you just commit .git/hooks/?
What is the difference between client-side and server-side Git hooks?
Ask Aria about Git Hooks — Automate with Every Git Action
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.