The Hook (The "Byte-Sized" Intro)
Your hook doesn't run. No error, no message — it's just ignored. 90% of the time, it's one of three things: not executable, wrong filename, or wrong path in PATH. Before you rewrite the hook or blame Git, check these three things first. Five minutes of troubleshooting saves hours of confusion.
📖 What is Hook Troubleshooting?
A systematic approach to diagnosing and fixing common Git hook problems.
Conceptual Clarity
The troubleshooting checklist:
| # | Check | How to Verify | Fix |
|---|---|---|---|
| 1 | Executable? | ls -la .git/hooks/pre-commit | chmod +x |
| 2 | Correct name? | No .sh extension, exact hook name | Rename file |
| 3 | Shebang line? | First line: #!/bin/sh | Add shebang |
| 4 | Correct path? | git config core.hooksPath | Update config |
| 5 | PATH available? | which node in hook context | Use full paths |
| 6 | No .sample? | File must NOT end in .sample | Remove suffix |
Common errors and fixes:
| Symptom | Likely Cause | Fix |
|---|---|---|
| Hook silently ignored | Not executable | chmod +x |
| Hook silently ignored | Wrong hooksPath | Check git config core.hooksPath |
| "command not found" | PATH issue in hook | Use full path: /usr/local/bin/node |
| "permission denied" | File not executable | chmod +x |
| Hook runs but doesn't block | exit 0 always | Check exit code logic |
Real-Life Analogy
Troubleshooting hooks is like debugging a light switch. First check: is it plugged in (executable)? Second: is it the right switch (filename)? Third: does the bulb work (script logic)? Check the simple things before assuming the wiring is bad.
Visual Architecture
Why It Matters
- Silent failures: Hooks don't show errors by default when misconfigured.
- Permission is #1: The most common issue is forgetting
chmod +x. - PATH differences: The hook runs in a different environment than your terminal.
- Quick debugging: Follow the checklist to resolve in 2 minutes.
Code
# ─── Step 1: Check if hook is executable ───
ls -la .git/hooks/pre-commit
# -rw-r--r-- ← NOT executable
# -rwxr-xr-x ← Executable ✅
chmod +x .git/hooks/pre-commit
# ─── Step 2: Verify the hook name ───
ls .git/hooks/
# pre-commit ← Correct ✅
# pre-commit.sh ← WRONG (no extension allowed)
# pre-commit.sample ← Disabled (remove .sample)
# ─── Step 3: Check the hooksPath config ───
git config core.hooksPath
# If set to .githooks/ but hooks are in .git/hooks/ → mismatch!
# ─── Step 4: Debug PATH issues ───
# Add to your hook for debugging:
echo "PATH is: $PATH" >&2
which node >&2
# Fix: use full paths
# Bad: npx lint-staged
# Good: /usr/local/bin/npx lint-staged
# ─── Step 5: Test the hook directly ───
.git/hooks/pre-commit
echo $?
# Should exit 0 (success) or 1 (block)
# ─── Step 6: Add debug output ───
# Temporarily add to the top of your hook:
set -x # Print every command as it runsKey Takeaways
- Check executable permission first — it's the #1 cause of silent failures.
- Hook filenames must be exact — no
.shextension, no.samplesuffix. - PATH in hook context differs from your terminal — use full paths.
- Test the hook directly by running it as a script:
.git/hooks/pre-commit.
Interview Prep
-
Q: What is the most common reason a Git hook doesn't run? A: The hook file is not executable. Fix with
chmod +x .git/hooks/<hook-name>. The second most common: the file has the wrong name (e.g.,pre-commit.shinstead ofpre-commit). -
Q: How do you debug a Git hook that fails with "command not found"? A: The hook runs in a limited shell environment where PATH may not include all your tools. Add
which <command>andecho $PATHto the hook for debugging. Fix by using full paths (e.g.,/usr/local/bin/node). -
Q: How do you test a Git hook without making a real commit? A: Run the hook script directly:
.git/hooks/pre-commit. Check the exit code withecho $?. 0 means it would allow the action; non-zero means it would block.