TechAnek

Essentials pre-commit git hook for Quality Software development

Essentials pre-commit git hook for Quality Software development

git svg | TechAnek

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.

What are git hooks?

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.

git hooks | TechAnek

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.

Why use pre-commit hooks?

  • Catch errors early: 
    Pre-commit hooks help catch errors before they are committed to the repository. By setting up checks such as syntax validation, linting, and unit tests, developers can avoid introducing bad code.
  • Maintain Code Quality: 
    Pre-commit hooks ensure that every commit meets a baseline level of quality. Automated checks like enforcing coding standards (e.g., PEP8 for Python) or detecting security vulnerabilities can help maintain a consistent codebase.
  • Save Time and Resources: 
    Running automated tests and linters before committing saves time by preventing broken code from reaching the main branch. This reduces the need for reviewers to spot trivial mistakes and allows teams to focus on higher-level issues.
  • Streamline Code Reviews: 
    When pre-commit hooks handle code formatting, linting, and other repetitive tasks, code reviewers can focus on the more important aspects—like the logic and architecture—rather than flagging minor issues like trailing commas or inconsistent indentation.

How pre-commit hooks work ?

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:

  • After changes are staged (git add).
  • Git runs the pre-commit hook script that defined in the .git/hooks/ folder.
  • If the script exits successfully (exit code 0), Git proceeds with the commit.
  • If the script fails (non-zero exit code), the commit is blocked, and git notify to fix the issues.

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.

How to enable pre-commit hooks for use ?

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:

  1. Locate the sample hook file in .git/hooks/.
  2. Rename the sample file (e.g.,  pre-commit.sample to pre-commit). 
  3. Edit the hook script to add custom logic.
  4. Make the script executable with necessary permission.
  5. Test the hook by committing changes to ensure it runs as expected.

Basic examples of pre-commit hooks in bash

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.

1. Check if python code is unformatted

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."

				
			
  • How it functions: This script checks all Python files in the repository. If they are not formatted correctly, the commit is blocked with a message asking the developer to format the code.
2. Preventing commit of debug statements

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."

				
			
  • How it functions: The script searches through all staged .js and .py files for console.log and print statements. If any are found, the commit is blocked, and the developer is notified.
3. Enforce commit message format and branch name

This pre-commit hook will ensure that:

  • Commit messages follow a specific format (starting with a lowercase letter and containing at least 5 words).
  • The current branch name begins with either 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."

				
			
  • How it functions: It checks that the current branch name either starts with 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.

Conclusion

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.