Git hooks are scripts that run automatically every time a specific event occurs in your Git repository. They provide a powerful way to enforce coding standards, automate tasks, and integrate with other tools. In this tutorial, we'll explore the different types of Git hooks, how they work, and best practices for using them effectively.
Git hooks are scripts that reside in the .git/hooks directory of your repository. They are written in any scripting language you prefer (e.g., Bash, Python, Ruby) and can be executed at various stages of the Git workflow. There are two main types of hooks:
Client-side hooks are triggered by actions performed locally, such as committing or pushing code. They can be used to validate changes before they are committed or pushed.
Let's create a pre-commit hook to ensure that all code changes are formatted according to Prettier standards before committing.
.git/hooks directory.pre-commit.#!/bin/bash
# Run Prettier on staged files
npx prettier --write $(git diff --cached --name-only)
# Check if there are any changes after formatting
if ! git diff-index --quiet HEAD --; then
echo "Prettier has reformatted your code. Please review and commit again."
exit 1
fi
echo "Commit is clean. Proceeding..."
exit 0
chmod +x .git/hooks/pre-commit
Now, every time you attempt to commit changes, Prettier will automatically format your code. If there are any changes after formatting, Git will prevent the commit and prompt you to review them.
Server-side hooks run on the remote server after receiving a push. They can be used to enforce rules about what gets accepted into the repository.
Let's create a pre-receive hook to prevent the merging of feature branches directly into the main branch.
.git/hooks directory of your repository.pre-receive.#!/bin/bash
# Read from standard input
while read oldrev newrev refname; do
# Check if the push is to the main branch
if [[ "$refname" == "refs/heads/main" ]]; then
# Get the list of branches being pushed
branches=$(git for-each-ref --format='%(refname:short)' refs/heads/)
# Check if any feature branch is being merged directly into main
for branch in $branches; do
if [[ "$branch" == "feature/*" ]]; then
echo "Error: Direct merging of feature branches into main is not allowed."
exit 1
fi
done
fi
done
echo "Push accepted."
exit 0
chmod +x .git/hooks/pre-receive
Now, any attempt to merge a feature branch directly into the main branch will be rejected.
Git hooks are a powerful feature of Git that can significantly enhance your workflow by automating tasks, enforcing standards, and integrating with other tools. By understanding the different types of hooks and best practices for using them, you can create a more efficient and reliable development process. Remember to always test and document your hooks to ensure they work as expected.
In the next section of our Git & GitHub course, we'll explore advanced Git workflows and strategies for managing large repositories. Stay tuned!