Git Hooks Integration
Git hooks allow you to run scripts before or after certain Git events, such as committing, pushing, or merging. GitLint provides built-in support for integrating with Git hooks, ensuring your commit messages are validated automatically as part of your Git workflow.
Understanding Git Hooks
Git hooks are scripts that Git executes before or after events such as commit, push, and receive. They're stored in the .git/hooks
directory of your repository and can be written in any scripting language.
For commit message validation, we primarily use the commit-msg
hook, which is triggered after you write a commit message but before the commit is finalized.
Automatic Git Hooks Installation
GitLint provides a convenient command to automatically install the necessary Git hooks for commit message validation:
# Install GitLint hooks in the current repository
gitlint hooks --install
# Force installation (overwrites existing hooks)
gitlint hooks --install --force
This command:
- Creates a
commit-msg
hook in your.git/hooks
directory - Makes the hook executable
- Configures the hook to use GitLint for validating commit messages
Manual Hook Installation
If you prefer to set up hooks manually or want to customize the hook behavior, you can create the hook file yourself:
# Create the commit-msg hook file
touch .git/hooks/commit-msg
chmod +x .git/hooks/commit-msg
Then add the following content to the file:
#!/bin/sh
# Get the commit message file path (passed by Git)
commit_msg_file=$1
# Run GitLint on the commit message
npx gitlint "$commit_msg_file" || exit 1
# Exit with success
exit 0
Customizing the Git Hook
You can customize the Git hook to add additional functionality or modify its behavior:
#!/bin/sh
# Get the commit message file path
commit_msg_file=$1
# Check if this is a merge commit (has a MERGE_MSG file)
if [ -f .git/MERGE_MSG ]; then
echo "Skipping validation for merge commit"
exit 0
fi
# Check if this is a revert commit
grep -q "^Revert " "$commit_msg_file" && exit 0
# Run GitLint with custom configuration
GITLINT_CONFIG_PATH="./custom-gitlint.config.js" npx gitlint "$commit_msg_file" || exit 1
# Additional custom validations
# ...
exit 0
Integrating with Other Git Hooks
Beyond commit message validation, you might want to integrate GitLint with other Git hooks:
Pre-push Hook
Validate all commit messages in a push:
#!/bin/sh
# Create a pre-push hook
cat > .git/hooks/pre-push << 'EOF'
#!/bin/sh
# Get the remote name and URL
remote="$1"
url="$2"
# Only run on pushes to specific branches
current_branch=$(git symbolic-ref --short HEAD)
if [ "$current_branch" = "main" ] || [ "$current_branch" = "develop" ]; then
echo "Validating commit messages before pushing to $current_branch..."
# Get the range of commits we're pushing
range=$(git merge-base HEAD origin/$current_branch)..HEAD
# Extract and validate each commit message
git log --pretty=%B $range | npx gitlint
if [ $? -ne 0 ]; then
echo "Push rejected: commit messages do not meet the guidelines."
exit 1
fi
fi
exit 0
EOF
chmod +x .git/hooks/pre-push
Post-checkout Hook
Switch to different validation rules based on the branch:
#!/bin/sh
# Create a post-checkout hook
cat > .git/hooks/post-checkout << 'EOF'
#!/bin/sh
# Get the branch name
branch=$(git symbolic-ref --short HEAD)
# Set different GitLint configurations based on branch
if [[ $branch == feature/* ]]; then
echo "Using feature branch GitLint configuration"
cp ./configs/feature-gitlint.config.js ./gitlint.config.js
elif [[ $branch == hotfix/* ]]; then
echo "Using hotfix branch GitLint configuration"
cp ./configs/hotfix-gitlint.config.js ./gitlint.config.js
else
echo "Using default GitLint configuration"
cp ./configs/default-gitlint.config.js ./gitlint.config.js
fi
exit 0
EOF
chmod +x .git/hooks/post-checkout
Sharing Git Hooks with Your Team
Git hooks aren't committed to the repository by default, so you'll need a way to share them with your team:
Option 1: Using Git Template Directory
# Create a template directory
mkdir -p ~/.git-templates/hooks
# Add commit-msg hook to the template
cp /path/to/your/commit-msg ~/.git-templates/hooks/
chmod +x ~/.git-templates/hooks/commit-msg
# Configure Git to use this template
git config --global init.templateDir ~/.git-templates
Then, when team members clone the repository or run git init
, they'll get the hooks.
Option 2: Using a Script in Your Repository
Add a setup script to your repository:
#!/bin/sh
# setup-hooks.sh
# Create the commit-msg hook
mkdir -p .git/hooks
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/sh
npx gitlint "$1" || exit 1
exit 0
EOF
chmod +x .git/hooks/commit-msg
echo "Git hooks installed successfully!"
Then, have team members run this script after cloning:
./setup-hooks.sh
Option 3: Using a Git Hook Manager
Consider using a Git hook manager like Husky or pre-commit to manage and share hooks:
// package.json with Husky
{
"name": "your-project",
"scripts": {
"prepare": "husky install"
},
"devDependencies": {
"gitlint": "^1.0.0",
"husky": "^8.0.0"
},
"husky": {
"hooks": {
"commit-msg": "npx gitlint $HUSKY_GIT_PARAMS"
}
}
}
Uninstalling Git Hooks
GitLint also provides a command to uninstall its Git hooks:
# Uninstall GitLint hooks
gitlint hooks --uninstall
This will remove the hooks that were installed by GitLint.
Troubleshooting
Common Issues
Issue: Hook isn't executing Solution: Check that the hook file is executable (chmod +x .git/hooks/commit-msg
)
Issue: Hook works locally but not in CI Solution: CI systems often use --no-verify
when committing, which bypasses hooks. Use a CI-specific validation approach instead.
Issue: Multiple tools competing for the same hook Solution: Consider using a hook manager like Husky that supports running multiple scripts for the same hook.