Git Hooks: Automate Workflow Like Pro
Learn: Git Hooks: Automate Workflow Like Pro
Welcome to TopperBlog! 👋
I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.
🎯 What I Write About:
• AI/ML Engineering & LLMs
• Web3 & Blockchain Development
• System Design & Architecture
• Interview Preparation (FAANG)
• Freelancing & Remote Work
• Modern Tech Stacks (Next.js, React, Rust, TypeScript)
• Performance Optimization & Best Practices
💼 Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.
📚 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.
🌐 Let's connect and grow together in this amazing tech journey!
#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering
Git Hooks: Automate Workflow Like a Pro
The Magic Behind Pre-Commit Hooks
Git hooks are like invisible ninjas in your repository—they silently watch your every move and spring into action at critical moments. Whether you're committing code, pushing to a remote, or merging branches, hooks can automate tedious tasks, enforce standards, and save your team from countless headaches.
Think of them as automated gatekeepers that ensure quality before code even reaches your repository.
The Story: Why We Need Git Hooks
The Scenario: Sarah's team was drowning in code review comments. Every pull request had the same issues: inconsistent formatting, missing tests, hardcoded credentials, and linting errors. The team was spending 40% of their time on trivial fixes instead of actual development.
Then Sarah discovered git hooks.
Within a week, her team's workflow transformed. Developers couldn't commit broken code even if they tried. Linters ran automatically. Tests executed before pushing. Credentials were caught before they leaked. Code reviews became about logic and architecture, not formatting.
The Result:
- 60% reduction in review cycle time
- Zero accidental credential leaks
- Consistent code style across the entire codebase
- Developers shipping features 30% faster
Pre-Commit Hooks: The Foundation
Pre-commit hooks fire before your commit is finalized. They're your first line of defense.
Setting Up Your First Hook
# Navigate to your git hooks directory
cd .git/hooks
# Create a pre-commit hook
touch pre-commit
chmod +x pre-commit
Basic Pre-Commit Hook Example
#!/bin/bash
# .git/hooks/pre-commit
echo "🔍 Running pre-commit checks..."
# Check for staged changes
if git diff --cached --name-only | grep -q "\.js$"; then
echo "📝 Linting JavaScript files..."
npm run lint -- --fix
if [ $? -ne 0 ]; then
echo "❌ Linting failed! Fix errors before committing."
exit 1
fi
fi
# Check for console.log statements
if git diff --cached | grep -q "console\.log"; then
echo "⚠️ Found console.log statements. Remove them!"
exit 1
fi
echo "✅ Pre-commit checks passed!"
exit 0
The Hook Arsenal: Essential Hooks Explained
1. Pre-Commit Hook (Most Important)
Runs before the commit is created. Perfect for:
- Linting and formatting
- Running tests
- Checking for secrets
- Validating file sizes
2. Commit-Msg Hook
Validates commit messages. Enforce conventional commits:
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG=$(cat $1)
# Check if commit follows conventional commits format
if ! echo "$COMMIT_MSG" | grep -qE "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?!?: .+"; then
echo "❌ Commit message must follow conventional commits:"
echo " feat(scope): description"
echo " fix(scope): description"
exit 1
fi
echo "✅ Commit message is valid!"
exit 0
3. Pre-Push Hook
Runs before pushing to remote. Catch issues before they go public:
#!/bin/bash
# .git/hooks/pre-push
echo "🚀 Running pre-push checks..."
# Run full test suite
npm test
if [ $? -ne 0 ]; then
echo "❌ Tests failed! Fix before pushing."
exit 1
fi
# Check for unresolved merge conflicts
if git diff --name-only --diff-filter=U | grep -q .; then
echo "❌ Unresolved merge conflicts detected!"
exit 1
fi
echo "✅ Ready to push!"
exit 0
4. Post-Merge Hook
Runs after merging branches. Useful for:
- Reinstalling dependencies
- Updating database migrations
- Refreshing build artifacts
#!/bin/bash
# .git/hooks/post-merge
# Check if package.json changed
if git diff HEAD@{1} HEAD --name-only | grep -q "package.json"; then
echo "📦 Dependencies changed. Running npm install..."
npm install
fi
# Check if migrations changed
if git diff HEAD@{1} HEAD --name-only | grep -q "migrations/"; then
echo "🗄️ Database migrations detected. Review before proceeding!"
fi
Pro Tips & Best Practices
Tip 1: Use a Hook Framework
Don't reinvent the wheel. Use Husky for Node.js projects:
npm install husky --save-dev
npx husky install
# Add a hook
npx husky add .husky/pre-commit "npm run lint"
npx husky add .husky/commit-msg 'echo "Validating commit message..."'
Tip 2: Combine with Lint-Staged
Only lint files that are actually staged:
npm install lint-staged --save-dev
{
"lint-staged": {
"*.js": "eslint --fix",
"*.css": "stylelint --fix",
"*.md": "prettier --write"
}
}
Tip 3: Make Hooks Bypassable (When Necessary)
Sometimes you need to skip hooks:
# Skip pre-commit hook
git commit --no-verify -m "Emergency fix"
# Skip pre-push hook
git push --no-verify
Tip 4: Share Hooks Across Team
Store hooks in version control:
# Create hooks directory in repo
mkdir -p .githooks
# Move hooks there
mv .git/hooks/pre-commit .githooks/
# Configure git to use this directory
git config core.hooksPath .githooks
# Team members run this once
git config core.hooksPath .githooks
Tip 5: Add Helpful Output
Make hooks user-friendly:
#!/bin/bash
# Use colors and emojis
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${YELLOW}🔍 Checking code quality...${NC}"
if npm run lint; then
echo -e "${GREEN}✅ All checks passed!${NC}"
else
echo -e "${RED}❌ Linting failed. Fix errors and try again.${NC}"
exit 1
fi
Tip 6: Performance Matters
Keep hooks fast. Slow hooks frustrate developers:
# ❌ Bad: Runs full test suite
npm test
# ✅ Good: Runs only affected tests
npm run test:affected
Advanced Hook Patterns
Pattern 1: Prevent Secrets from Leaking
#!/bin/bash
# Detect AWS keys, API tokens, etc.
PATTERNS=(
"AKIA[0-9A-Z]{16}" # AWS Access Key
"aws_secret_access_key"
"private_key"
"password.*="
)
for pattern in "${PATTERNS[@]}"; do
if git diff --cached | grep -iE "$pattern"; then
echo "❌ Potential secret detected!"
exit 1
fi
done
Pattern 2: Enforce Branch Naming
#!/bin/bash
# .git/hooks/pre-commit
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if ! echo "$BRANCH" | grep -qE "^(main|develop|feature|bugfix|hotfix)\/"; then
echo "❌ Branch name must follow pattern: feature/*, bugfix/*, etc."
exit 1
fi
Pattern 3: Auto-Format on Commit
#!/bin/bash
# Auto-format and re-stage files
npm run format
git add .
Troubleshooting Common Issues
| Issue | Solution |
| Hook not executing | Check file permissions: chmod +x .git/hooks/pre-commit |
| Hook runs but changes aren't staged | Use git add to re-stage modified files |
| Team members skip hooks | Use Husky to enforce hooks across team |
| Hooks too slow | Optimize with lint-staged or parallel execution |
| Hook works locally but not in CI | Ensure CI environment has same dependencies |
Conclusion
Git hooks transform your workflow from reactive (catching issues in review) to proactive (preventing issues before they happen). Start with pre-commit hooks for linting and formatting, add commit-msg validation, then expand to pre-push and post-merge hooks.
The magic isn't in the hooks themselves—it's in the consistency and automation they bring to your team's development process. Your future self (and your code reviewers) will thank you.
Start small. Automate wisely. Ship better code.