The Hook (The "Byte-Sized" Intro)
A Git hook is just a script. Not a plugin. Not a framework. A plain script in .git/hooks/ with the right name and chmod +x. A 3-line pre-commit hook can prevent you from ever committing a console.log again. Let's write one from scratch โ no tools, no dependencies, just a shell script.
๐ What is Writing a Simple Hook?
Creating a hook from scratch: choosing the hook event, writing the script, making it executable, and testing it.
Conceptual Clarity
The anatomy of a hook:
| Part | What It Is | Example |
|---|---|---|
| Shebang | Tells the OS what interpreter to use | #!/bin/sh |
| Logic | The checks or actions to perform | npm run lint |
| Exit code | Determines if the action proceeds | exit 0 (allow) / exit 1 (block) |
Hook creation checklist:
- Create the file:
.git/hooks/<hook-name>(no extension) - Add shebang line:
#!/bin/sh - Write your logic
- Make it executable:
chmod +x .git/hooks/<hook-name> - Test it: trigger the Git event
Real-Life Analogy
Writing a hook is like programming a door sensor. Choose when it triggers (opening the door = committing), what it checks (did you grab your keys?), and what happens if the check fails (the door stays locked).
Visual Architecture
Why It Matters
- No dependencies: Hooks are plain scripts โ no tools needed.
- Any language: Bash, Python, Node, Ruby โ anything executable.
- Immediate effect: Create the file, make it executable, done.
- Foundation: Understanding raw hooks helps you use tools like Husky effectively.
Code
# โโโ Hook 1: Block console.log โโโ
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
# Prevent committing console.log statements
if git diff --cached --name-only | xargs grep -l "console.log" 2>/dev/null; then
echo "โ Remove console.log before committing!"
echo " Found in the files above."
exit 1
fi
echo "โ
No console.log found. Proceeding."
EOF
chmod +x .git/hooks/pre-commit
# โโโ Hook 2: Enforce conventional commit message โโโ
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/sh
MSG=$(cat "$1")
if ! echo "$MSG" | grep -qE "^(feat|fix|chore|docs|refactor|test): "; then
echo "โ Message must start with: feat|fix|chore|docs|refactor|test"
echo " Got: $MSG"
exit 1
fi
EOF
chmod +x .git/hooks/commit-msg
# โโโ Hook 3: Run tests before push โโโ
cat > .git/hooks/pre-push << 'EOF'
#!/bin/sh
echo "๐งช Running tests before push..."
npm test
EOF
chmod +x .git/hooks/pre-push
# โโโ Test the hook โโโ
echo "console.log('debug')" >> test.js
git add test.js
git commit -m "test"
# โ Remove console.log before committing!Key Takeaways
- Hooks are just scripts โ no framework or tools needed.
- Three requirements: correct name, shebang line, executable permission.
exit 0allows the action;exit 1blocks it with an error message.git diff --cachedis the key to checking only staged files.
Interview Prep
-
Q: How do you create a Git hook from scratch? A: Create a file in
.git/hooks/named after the hook event (e.g.,pre-commit), add a shebang line, write your check logic, and make it executable withchmod +x. -
Q: How does a pre-commit hook check only staged files? A: Using
git diff --cached --name-onlyto get the list of staged files, then running checks (lint, grep) only on those files. -
Q: Can hooks be written in any language? A: Yes โ any executable script works. Use the appropriate shebang:
#!/bin/shfor shell,#!/usr/bin/env python3for Python,#!/usr/bin/env nodefor Node.js.