Git Hooks are scripts that run automatically at specific points in a Git workflow. They allow you to automate tasks, enforce rules, or integrate with other tools.
Git hooks are customizable scripts that Git executes before or after specific events, such as commits, merges, or pushes. Hooks reside in the .git/hooks
directory of a repository and can be tailored to meet your workflow requirements.
These run on the developer’s machine and are triggered by actions like committing, merging, or pushing.
Examples:
pre-commit
: Runs before a commit is created.commit-msg
: Validates or formats commit messages.pre-push
: Executes before pushing changes to a remote repository.
These run on the server and are triggered by events like receiving a push.
Examples:
pre-receive
: Validates incoming changes before they are applied.post-receive
: Triggers actions like deploying code after a push.update
: Checks changes to individual branches during a push.
Hook | Description | Trigger Event |
---|---|---|
pre-commit |
Validates changes before committing. | git commit |
commit-msg |
Validates the commit message format. | git commit |
post-commit |
Runs tasks after a commit is created. | git commit |
pre-push |
Runs checks before pushing to a remote. | git push |
pre-receive |
Validates incoming changes on the server. | git push to a remote repository. |
post-receive |
Runs tasks like CI/CD after a push is received. | git push to a remote repository. |
The hooks directory is located at:
.git/hooks
-
Rename the sample hook file (e.g.,
pre-commit.sample
) to remove the.sample
extension:mv .git/hooks/pre-commit.sample .git/hooks/pre-commit
-
Open the file in a text editor:
nano .git/hooks/pre-commit
-
Add your script logic.
chmod +x .git/hooks/pre-commit
Run a linter to ensure code quality before committing:
#!/bin/bash
# Run ESLint on staged files
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')
if [ -n "$FILES" ]; then
eslint $FILES
if [ $? -ne 0 ]; then
echo "Linting failed. Commit aborted."
exit 1
fi
fi
Ensure commit messages follow a specific format:
#!/bin/bash
# Enforce commit message format
MESSAGE=$(cat $1)
if ! [[ $MESSAGE =~ ^[A-Z]+\-[0-9]+\: ]]; then
echo "Commit message must start with JIRA ID (e.g., PROJ-123: Fix bug)"
exit 1
fi
Send a Slack notification after a commit:
#!/bin/bash
# Send a notification to Slack
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"New commit pushed: '"$(git log -1 --pretty=%B)"'"}' \
https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
Git hooks are not version-controlled by default. To share hooks:
- Store them in a directory, such as
.githooks/
. - Use
core.hooksPath
to point Git to the shared directory:git config core.hooksPath .githooks
- Keep Hooks Simple: Avoid writing overly complex scripts.
- Test Thoroughly: Ensure hooks work correctly and don’t disrupt workflows.
- Document Hooks: Clearly document what each hook does and how to disable or modify it.
- Use for Automation: Automate repetitive tasks like linting, formatting, or notifying teams.
Command | Description |
---|---|
chmod +x .git/hooks/<hook-name> |
Make the hook script executable. |
git config core.hooksPath <path> |
Set a custom directory for hooks. |
ls .git/hooks |
List all available hooks. |
- Non-Portable Tasks: Hooks are not shared by default, so tasks that need to run across teams are better suited for CI/CD pipelines.
- Critical Logic: Avoid placing critical business logic in hooks since they can be bypassed.
Git hooks are powerful for automating tasks, enforcing rules, and improving workflows. By using hooks effectively, you can save time, ensure consistency, and enhance team collaboration.
Next Steps: Git Bisect