This guide explains how to use Git hooks, provides examples of common hooks, and explores their role in automation. By mastering Git hooks, you can enhance your development process and reduce manual overhead.

What Are Git Hooks?

Git hooks are customizable scripts that run in response to repository events like commits, merges, and pushes. They are stored in the .git/hooks directory of your repository. Git provides two types of hooks:

  • Client-Side Hooks: Triggered by operations such as commits and merges, these hooks run on the developer's machine.
  • Server-Side Hooks: Triggered by operations such as pushes, these hooks run on the Git server.

Setting Up Git Hooks

To set up a Git hook:

  1. Navigate to the .git/hooks directory in your repository.
  2. Create or modify the appropriate hook script (e.g., pre-commit).
  3. Make the script executable:
    chmod +x .git/hooks/pre-commit
    

Common Git Hooks

1. Pre-Commit Hook

The pre-commit hook runs before a commit is created. It is often used to check code formatting, run tests, or validate changes.

#!/bin/sh
# Run tests before committing
echo "Running tests..."
npm test
if [ $? -ne 0 ]; then
  echo "Tests failed. Aborting commit."
  exit 1
fi

2. Commit-Msg Hook

The commit-msg hook ensures commit messages follow a specified format.

#!/bin/sh
# Enforce a commit message template
commit_message=$(cat $1)
if ! echo "$commit_message" | grep -qE "^(feat|fix|docs|style|refactor|test|chore): .+"; then
  echo "Commit message must start with a valid prefix (e.g., feat, fix)."
  exit 1
fi

3. Pre-Push Hook

The pre-push hook runs before changes are pushed to a remote repository. It is useful for running tests or validating branch rules.

#!/bin/sh
# Ensure the main branch is not pushed directly
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$current_branch" = "main" ]; then
  echo "Direct pushes to main are not allowed. Use a pull request instead."
  exit 1
fi

4. Post-Commit Hook

The post-commit hook runs after a commit is created. It can be used for notifications or logging.

#!/bin/sh
# Notify team members of a new commit
echo "Commit successful. Notify team..."
curl -X POST -d "A new commit was made on branch $(git rev-parse --abbrev-ref HEAD)" https://example.com/notify

Example: Using Git Hooks in a .NET Project

Suppose you’re working on a .NET project and want to ensure code style consistency before committing changes. Set up a pre-commit hook to run a linter:

#!/bin/sh
# Pre-commit hook for linting .NET code
echo "Running .NET Code Analyzer..."
dotnet format
if [ $? -ne 0 ]; then
  echo "Code formatting issues detected. Please fix them before committing."
  exit 1
fi

Save this script as .git/hooks/pre-commit and make it executable. Now, every time you commit changes, the hook ensures code formatting is consistent.

Best Practices for Git Hooks

  • Keep hooks lightweight: Avoid long-running scripts that slow down workflows.
  • Use version control: Store shared hooks in your repository to ensure consistency across the team.
  • Use tools like Husky: For JavaScript projects, tools like Husky simplify hook management.

Limitations of Git Hooks

While powerful, Git hooks have some limitations:

  • Hooks are not versioned by default. You must share them manually or use tools like Husky.
  • Hooks are local to each repository and must be set up individually on every machine.

Conclusion

Git hooks are a valuable tool for automating workflows and maintaining consistency in your projects. By leveraging hooks effectively, you can streamline processes, enforce best practices, and focus on writing quality code. Explore Git hooks today to optimize your development workflow.