Home/Learn/Git/Git Hooks — Automate with Every Git Action

Git Hooks — Automate with Every Git Action

Advanced
Advanced

Git 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).

pre-commit hook — run ESLint
# 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-commit

Enforcing Commit Message Format

The commit-msg hook receives the commit message file as $1. Use it to enforce Conventional Commits or ticket number prefixes.

commit-msg validation + Husky setup
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 $1

pre-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.

pre-push and server-side hooks
# .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 PRs

Key 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 Aria
1

What are Git hooks? Give three examples of how you would use them.

Medium
2

How do you share Git hooks with your team? Why can't you just commit .git/hooks/?

Hard
3

What is the difference between client-side and server-side Git hooks?

Medium

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.

Loading discussion…