Git Hooks Basics: Automating Quality Control Locally
Learn how to use Git hooks to automate quality control. Create your first pre-commit hook to prevent broken code from ever reaching your repository.

Previously in this course, we discussed Advanced Branching Patterns: Mastering Release Branches and Hotfixes to manage complex delivery cycles. Now that your team is branching effectively, you need a way to ensure that the code being merged is actually clean. This lesson introduces git hooks, a powerful feature for local automation and consistent quality control.
What Are Git Hooks?
Git hooks are scripts that Git executes automatically when specific events occur in your repository. Think of them as "event listeners" for your version control system. When you perform an action like committing code, pushing to a remote, or checking out a branch, Git checks the .git/hooks directory for a corresponding script. If it finds one, it runs it.
Hooks are categorized into two main types:
- Client-side hooks: Triggered by operations on your local machine (e.g.,
pre-commit,pre-push). These are perfect for local quality checks. - Server-side hooks: Triggered by network operations on the server hosting your repository (e.g.,
pre-receive). These are typically managed by platform administrators.
For our daily workflow, we focus on client-side hooks to catch errors before they even become part of our history. As we discussed in Automated Gatekeeping: Stop Broken Code Before It Merges, while CI pipelines are your final safety net, local hooks provide immediate feedback, saving you from the "commit-push-fail-revert" loop.
Creating Your First Pre-Commit Hook
A pre-commit hook runs right after you type git commit but before the commit is actually created. If the script exits with a non-zero status, Git aborts the commit. This is the perfect place to run linters, formatters, or unit tests.
Let’s implement a simple hook that prevents you from committing if a specific "TODO" string exists in your files—a common way to ensure unfinished code doesn't slip into the main branch.
- Navigate to the hooks directory:
Inside your project, go to the hidden
.gitfolder:Bashcd .git/hooks - Create the script:
You will see several sample files ending in
.sample. Create a new file namedpre-commit(no extension):Bashtouch pre-commit - Add your logic:
Open the file in your editor and add this content:
Bash
#!/bin/sh # Check for "TODO" in staged files if git diff --cached | grep -q "TODO"; then echo "Error: You have a TODO in your code. Please resolve it before committing." exit 1 fi exit 0 - Make it executable:
Git will not run scripts that aren't executable. Run this command:
Bash
chmod +x pre-commit
Now, try adding a file containing the string "TODO" and running git commit. Git will block your commit, forcing you to remove the note before proceeding. This is exactly how you enforce How to Use Git Hooks to Automate Your Workflow Guardrails.
Hands-on Exercise
In our ongoing project, we want to ensure no one accidentally commits a file containing a sensitive API key (following our work in Handling Sensitive Data: Protecting Secrets in Git/GitHub).
Your Task:
Modify your pre-commit hook to search for the string API_KEY=. If it finds it, print a warning and exit with status 1. Verify it works by creating a file config.env with that string, staging it, and attempting to commit.
Common Pitfalls
- Permissions: Forgetting
chmod +xis the #1 reason hooks fail to run. If your hook isn't firing, check your file permissions. - The "Hooks are not versioned" problem: Git hooks live in the
.git/hooksfolder, which is not tracked by version control. This means your teammates won't automatically get the same hooks you have. To solve this, many teams store their hooks in a folder likescripts/git-hooksand use a setup script to copy them into the.git/hooksdirectory upon project initialization. - Over-engineering: Don't run a 10-minute full suite of integration tests in a
pre-commithook. You’ll become frustrated and eventually bypass the hook usinggit commit --no-verify. Keep local hooks fast (under 5 seconds).
FAQ
Can I bypass a hook if I really need to?
Yes, you can use the --no-verify flag with your commit command: git commit -m "msg" --no-verify. Use this sparingly.
Where can I see what happened if a hook fails?
The output of your script is printed directly to your terminal. If your script uses echo or printf, you will see those messages in the terminal before the commit process halts.
Do hooks work on Windows?
Yes, but ensure your shebang line (#!/bin/sh) points to a valid shell, such as Git Bash’s sh.exe.
Recap
Git hooks are an essential tool for maintaining repository hygiene. By intercepting the commit process, you can automate quality checks, preventing common errors from entering your history. Remember to keep them fast, and share them with your team by committing them to a tracked folder in your repository.
Up next: We will look at managing project dependencies by exploring Submodules and Dependencies.
Work with me

AI Automation & Agentic Workflow Development
Automate the repetitive work eating your time — content pipelines, data workflows, and agentic AI tasks that run themselves.

CI/CD Pipeline & Docker Containerization
Ship with confidence: automated CI/CD pipelines and Docker setups so every push is tested and deployed — no more manual, error-prone releases.


