Introduction
Git hooks are powerful scripts that run automatically before or after specific Git events, such as commits, pushes, or merges. They help enforce code quality, run tests, and prevent common mistakes before changes are committed or pushed to a repository.
Two of the most useful Git hooks are:
- pre-commit – Runs before a commit is finalized.
- pre-push – Runs before changes are pushed to a remote repository.
By automating checks like linting, testing, and formatting, Git hooks ensure that only clean, well-tested code makes it into your repository.
How to Use Git Hooks
Git hooks are stored in the .git/hooks
directory of your repository. By default, Git provides sample hooks, but you can replace them with custom scripts.
1. Locating Git Hooks
Navigate to your Git repository and check the .git/hooks
directory:
cd your-repo/.git/hooks
ls -la
You’ll see sample hooks like pre-commit.sample
and pre-push.sample
.
2. Enabling a Git Hook
To activate a hook, remove the .sample
extension and make the script executable:
mv pre-commit.sample pre-commit
chmod +x pre-commit
3. Writing a Custom Hook (Example)
Let’s create a pre-commit
hook that runs ESLint (JavaScript linter) before allowing a commit:
#!/bin/sh
echo "Running ESLint..."
eslint .
if [ $? -ne 0 ]; then
echo "ESLint found errors. Commit aborted."
exit 1
fi
echo "Checks passed. Proceeding with commit."
exit 0
Save this as .git/hooks/pre-commit
and make it executable (chmod +x
).
Common Use Cases for Git Hooks
1. Pre-Commit Hook
- Linting: Ensure code follows style guidelines (ESLint, RuboCop, Pylint).
- Unit Tests: Run quick tests before committing.
- Preventing Secrets: Block accidental commits of API keys or passwords.
Example: Python project using pytest
and black
for formatting.
#!/bin/sh
echo "Running Black formatter..."
black --check .
if [ $? -ne 0 ]; then
echo "Code formatting issues found. Run 'black .' to fix."
exit 1
fi
echo "Running pytest..."
pytest
if [ $? -ne 0 ]; then
echo "Tests failed. Commit aborted."
exit 1
fi
exit 0
2. Pre-Push Hook
- Integration Tests: Run longer tests before pushing.
-
Branch Protection: Prevent pushing to
main
directly. -
Dependency Checks: Ensure
package-lock.json
is updated.
Example: Preventing pushes to main
branch.
#!/bin/sh
current_branch=$(git symbolic-ref --short HEAD)
protected_branch="main"
if [ "$current_branch" = "$protected_branch" ]; then
echo "Pushing directly to 'main' is not allowed. Use a PR."
exit 1
fi
exit 0
Tips and Tricks
1. Using Husky for Easier Hook Management (Node.js)
Instead of manually managing hooks, use Husky to configure them via package.json
:
npm install husky --save-dev
npx husky init
Then add a pre-commit
hook:
npx husky add .husky/pre-commit "npm test"
2. Bypassing Hooks (When Needed)
Sometimes you need to skip hooks (e.g., for a quick fix):
git commit --no-verify # Skips pre-commit hook
git push --no-verify # Skips pre-push hook
3. Sharing Hooks Across a Team
Since .git/hooks
isn’t version-controlled, use a hooks/
directory in your repo and set them up via a script:
#!/bin/sh
cp hooks/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Conclusion
Git hooks (pre-commit
, pre-push
) are essential for automating checks and maintaining code quality. Whether it’s running linters, tests, or branch protection, hooks help catch errors early and enforce best practices.
Key Takeaways:
✔ Automate linting, testing, and formatting with pre-commit
.
✔ Use pre-push
for heavier checks like integration tests.
✔ Tools like Husky simplify hook management in Node.js projects.
✔ Always ensure hooks are executable (chmod +x
).
Further Reading
Up Next in the Series: git config --global alias
– Create custom Git shortcuts
Daily advance GIT tips in your inbox---worth starting? Respond to my poll here🚀
For more useful and innovative tips and tricks, Let's connect on Medium
Hello content creators! We’re thrilled to announce We're offering an exclusive token airdrop to celebrate our authors' impact in Web3. Click here here (for verified Dev.to users only). – Dev.to Airdrop Desk