In the fast-moving world of software development, it’s vital to make sure that high-quality code is added to repositories to keep software reliable and reduce technical problems. Pre-commit Git hooks are a very useful tool for making sure code meets standards, finding issues early, and promoting better development habits before changes are committed. This blog will explore the basics of pre-commit Git hooks, explain why they’re important, and show how to use them for quality software development.
Git hooks are scripts that automatically run at different stages of the Git process. These hooks let developers automate tasks such as running tests, checking for code style issues, or performing other checks before or after specific Git commands.
In this blog, we’ll focus on pre-commit hooks, which are part of the client-side hooks. These hooks run just before a commit is recorded, allowing developers to ensure that the code meets certain quality standards.
Pre-commit hooks are stored in your repository’s .git/hooks
directory and are executed automatically by Git before each commit. Each hook is essentially a script that Git runs before or after specific Git commands (like committing, pushing, or merging).
Here’s how it works in practice:
git add
)..git/hooks/
folder.Note: Pre-commit hooks can be written in any language executable by the system, such as Bash, Python, Node.js, or Ruby. As long as the script is executable, it can run checks before a commit. This provides flexibility to customize hooks based on the specific needs and environment of the project.
After writing pre-commit hook scripts (in Bash or any other language), they need to be enabled for Git to execute. Here’s how to do that:
.git/hooks/
. pre-commit.sample to pre-commit
). Pre-commit hooks are a great way to automate checks before committing code to your repository. Writing pre-commit hooks in Bash is common because it’s lightweight and widely supported. Below are some practical examples that can be easily added to your Git project.
The Python code formatter Black is used in this example, to check whether the Python code is formatted correctly. If it’s not, the commit will be blocked, and the developer is prompted to fix it before proceeding.
#!/bin/bash
# Pre-commit hook to check Python formatting with Black
echo "Checking Python code formatting..."
# Run black in check mode (it will not modify the files, only report issues)
black --check .
# If the exit code is not zero, prevent the commit
if [ $? -ne 0 ]; then
echo "Python code is not formatted correctly. Please run 'black' to format your code."
exit 1
fi
echo "Formatting check passed."
This hook checks for any console.log
(in JavaScript) or print
statements (in Python), which are often left behind unintentionally after debugging. The script will scan the staged files and block the commit if any debug statements are found.
#!/bin/bash
# Pre-commit hook to prevent committing debug statements
echo "Checking for debug statements..."
# Search for 'console.log' in JavaScript and 'print' in Python files
if git diff --cached --name-only | grep -E '\.js$|\.py$' | xargs grep -E 'console\.log|print'; then
echo "Debug statements found (console.log or print). Please remove them before committing."
exit 1
fi
echo "No debug statements found."
.js
and .py
files for console.log
and print
statements. If any are found, the commit is blocked, and the developer is notified.This pre-commit hook will ensure that:
feature/
or debug/
.
#!/bin/bash
# Pre-commit hook to enforce commit message format and branch name
Enforce branch name starts with 'feature/' or 'debug/'
current_branch=$(git rev-parse --abbrev-ref HEAD)
if ! [[ "$current_branch" =~ ^(feature|bugfix )/ ]]; then
echo "Error: Branch name must start with 'feature/' or 'debug/'."
exit 1
fi
echo "Branch name is valid."
feature/
or debug/
, or is named dev
or main
. If either the commit message or the branch name doesn’t meet these conditions, the commit is blocked, helping maintain clear commit history and consistent branch naming conventions across the team.Pre-commit Git hooks act as a quality control system, running in the background to ensure that code meets required standards. They help catch errors early, enforce consistent coding styles, and prevent accidental commits of broken code or sensitive data. Incorporating pre-commit hooks into the workflow ensures that the codebase remains clean, secure, and consistent from the first commit. Implementing them can lead to a more efficient and error-free software development process.