You know that gut-punch feeling when you push broken code, forget to run tests, or write a commit message so vague it could be the title of a Christopher Nolan film?

Yep. Been there, done that.

But what if I told you Git can automate that slap-on-the-wrist your tech lead usually gives you during code review?

Meet Git Hooks — your silent sidekick for clean commits, consistent messages, and fewer "oops" moments.


💡 What Are Git Hooks?

Git hooks are executable scripts that Git runs before or after certain events like commits, pushes, merges, rebases, and more. Think of them as little robot assistants standing guard over your version control flow.

They live in this path (by default):

.git/hooks/

...and are disabled until you make them executable and give them real jobs.


🦸‍♂️ Why Should You Care?

Let’s be honest: we're all human.

We forget to run tests.

We commit debug.log.

We write commit messages like fix stuff.

Git hooks automate the "are-you-sure" part of development — catching mistakes before they hit the repo.

Now, let me show you the ones you're actually likely to use in real life — the ones that save developers from daily embarrassment.


💡 pre-commitStop Bad Code Before It Happens

When it runs: Before a commit is finalized.

Why it's useful:
Block broken, unformatted, or careless code from entering your repo. Consider this your first line of defense.

Example: Lint your code before committing

#!/bin/sh
echo "Linting your code..."
npm run lint
if [ $? -ne 0 ]; then
  echo "❌ Linting failed! Fix errors before committing."
  exit 1
fi

📌 Save this in .git/hooks/pre-commit and make it executable:

chmod +x .git/hooks/pre-commit

💡 commit-msgEnforce Commit Message Discipline

When it runs: After you write your commit message, before the commit is saved.

Why it's useful:
Protects your repo from cryptic, non-informative commit messages like:

misc changes

Example: Enforce Conventional Commits

#!/bin/sh

message=$(cat "$1")
pattern="^(feat|fix|chore|docs|style|refactor|test|perf|ci|build|revert)(\(.+\))?: .{1,50}"

if ! echo "$message" | grep -qE "$pattern"; then
  echo "❌ Invalid commit message!"
  echo "✅ Format should be: feat(scope): description"
  exit 1
fi

💡 pre-pushThe Final Defense Line

When it runs: Before your code is pushed to the remote.

Why it's useful:
Ensure tests pass or builds are successful before anyone else gets your code.

Example: Run tests before push

#!/bin/sh

echo "Running tests before push..."
npm test
if [ $? -ne 0 ]; then
  echo "❌ Tests failed! Push aborted."
  exit 1
fi

💡 post-mergeSync After Merging

When it runs: After a git merge completes.

Why it's useful:
Prevent those "works on my machine" moments after pulling changes that added new dependencies.

Example: Auto-install dependencies if package.json changed

#!/bin/sh

if git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD | grep -q "package.json"; then
  echo "package.json changed — running npm install..."
  npm install
fi

💡 post-checkoutWelcome to Your New Branch

When it runs: Every time you checkout a branch or commit.

Why it's useful:
Automatically reset environment configs or remind yourself which branch you're on.

Example: Notify current branch

#!/bin/sh

branch=$(git rev-parse --abbrev-ref HEAD)
echo "✅ You're now on branch: $branch"

📚 Other Git Hooks You Should Know (But Use When Needed)

Hook Name Purpose & When It Runs
applypatch-msg Before applying a patch with git am. Validate commit messages in patches.
pre-applypatch Before a patch is applied. Often used for prep steps.
post-applypatch After a patch is applied. Good for notifications or rebuilds.
prepare-commit-msg Modify auto-generated commit messages (e.g., squash, merge templates).
post-commit After a commit completes. Log events or trigger notifications.
pre-rebase Before a rebase starts. Block protected branches or warn users.
pre-merge-commit Before a merge commit is created. Validate merge intentions.
pre-auto-gc Before Git performs automatic garbage collection.
post-rewrite After rewriting commits via rebase or amend. Useful for cleanup.

🔗 How to Share Hooks Across Teams?

Git doesn’t track .git/hooks (by design) — so if you want team-wide consistency, you have two main solutions:

1. Husky

  • Perfect for JavaScript/TypeScript projects.

  • Hooks are stored inside your version-controlled codebase.

  • Easy to set up with npx husky install.

2. Lefthook

  • Language-agnostic.

  • Great for teams working across different stacks.

  • Centralizes hooks under version control.


💡 Final Thoughts

Git Hooks won't write better code for you — but they will:

  • Save you from human error.

  • Make you look like the professional you pretend to be on LinkedIn.

  • Keep your team's history clean and consistent.

Start simple:

  • pre-commit for code quality.
  • commit-msg for consistent commit messages.
  • pre-push for last-minute sanity checks.

And watch how your workflow instantly levels up.