Skip to main content

Hooks & Automation

Quick Summary

Git hooks are scripts that run automatically when specific Git events occur (commit, push, merge, etc.). They let you enforce code quality (lint before commit), run tests (before push), and automate repetitive tasks — all without relying on CI/CD.


Available Hooks

HookTriggerCommon Use
pre-commitBefore commit is createdLint, format, check secrets
commit-msgAfter message is enteredValidate commit message format
pre-pushBefore push to remoteRun tests
post-mergeAfter merge completesInstall dependencies
post-checkoutAfter branch switchSetup environment
prepare-commit-msgBefore editor opensAuto-populate message template

Creating a Hook

Hooks live in .git/hooks/. Create a file with the hook name (no extension) and make it executable:

# Create a pre-commit hook
nano .git/hooks/pre-commit
#!/bin/sh
# pre-commit hook: run linter before allowing commit

echo "Running linter..."
npm run lint

if [ $? -ne 0 ]; then
echo "❌ Lint failed. Fix errors before committing."
exit 1 # Block the commit
fi

echo "✅ Lint passed."
exit 0 # Allow the commit
# Make it executable
chmod +x .git/hooks/pre-commit

Useful Hook Examples

Pre-commit: Check for Debug Statements

#!/bin/sh
# Block commits containing console.log or debugger

BLOCKED=$(git diff --cached --name-only | xargs grep -l "console\.log\|debugger" 2>/dev/null)

if [ -n "$BLOCKED" ]; then
echo "❌ Found debug statements in:"
echo "$BLOCKED"
echo "Remove console.log/debugger before committing."
exit 1
fi

Commit-msg: Enforce Conventional Commits

#!/bin/sh
# Require conventional commit format

MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf)(\(.+\))?: .{3,}"

if ! echo "$MSG" | grep -qE "$PATTERN"; then
echo "❌ Commit message must follow Conventional Commits format:"
echo " feat: add login page"
echo " fix(auth): resolve timeout issue"
exit 1
fi

Pre-push: Run Tests

#!/bin/sh
echo "Running tests before push..."
npm test

if [ $? -ne 0 ]; then
echo "❌ Tests failed. Fix before pushing."
exit 1
fi

Sharing Hooks with the Team

Git hooks live in .git/hooks/ which is not tracked by Git. Solutions:

Option 1: Husky (Node.js projects)

# Install Husky
npm install --save-dev husky

# Initialize
npx husky init

# Add a pre-commit hook
echo "npm run lint" > .husky/pre-commit

package.json:

{
"scripts": {
"prepare": "husky"
}
}

Option 2: Custom hooks directory

# Store hooks in a tracked directory
mkdir -p .githooks

# Configure Git to use it
git config core.hooksPath .githooks

Best Practices

  • Keep hooks fast — slow pre-commit hooks frustrate developers
  • Use Husky or core.hooksPath — ensure the whole team uses the same hooks
  • Don't replace CI/CD — hooks are local; CI/CD is the authoritative check
  • Allow bypass for emergenciesgit commit --no-verify skips hooks
  • Test hooks — a broken hook can block all commits

What's Next

  1. Common Errors — Fix frequent Git mistakes
  2. Undoing Changes — Undo commits, merges, and staged changes