hooks Git Command Guide
The githooks system provides a way to automatically trigger custom scripts at key points in Git operations. Hooks enable automation of workflows, enforcement of policies, and integration with external tools when performing Git operations.
Hook Types and Categories:
Section titled “Hook Types and Categories:”Client-Side Hooks (Local Repository):
Section titled “Client-Side Hooks (Local Repository):”| Hook | Description | Trigger Point |
|---|---|---|
pre-commit | Before commit creation | git commit |
prepare-commit-msg | Commit message template | git commit |
commit-msg | Commit message validation | git commit |
post-commit | After commit creation | git commit |
pre-merge-commit | Before merge commit creation | git merge |
post-merge | After merge completion | git merge |
pre-applypatch | Before applying patch | git am |
applypatch-msg | Patch message validation | git am |
post-applypatch | After applying patch | git am |
pre-rebase | Before rebase begins | git rebase |
post-rewrite | After history rewriting commands | git rebase/cherry-pick |
post-checkout | After checkout operations | git checkout |
post-merge | After successful merge | git pull/merge |
Server-Side Hooks (Remote Repository):
Section titled “Server-Side Hooks (Remote Repository):”| Hook | Description | Trigger Point |
|---|---|---|
pre-receive | Before any ref update | git push |
update | Before each ref update | git push |
post-receive | After all ref updates complete | git push |
post-update | After repository update completes | git push |
push-to-checkout | Handle push-to-deploy | git push |
Configuration and Email Hooks:
Section titled “Configuration and Email Hooks:”| Hook | Description | Use Case |
|---|---|---|
pre-auto-gc | Before automatic garbage collection | Repository maintenance |
post-rewrite | After rewriting operations | History modification tracking |
Hook Installation and Setup:
Section titled “Hook Installation and Setup:”Basic Hook Installation:
Section titled “Basic Hook Installation:”# Make hook executablechmod +x .git/hooks/pre-commit
# Create custom hook scriptcat > .git/hooks/pre-commit << 'EOF'#!/bin/bash# Pre-commit hook logic hereecho "Running pre-commit checks..."EOF
chmod +x .git/hooks/pre-commitHook Template Setup:
Section titled “Hook Template Setup:”# Copy from template directorycp .git/hooks/pre-commit.sample .git/hooks/pre-commitchmod +x .git/hooks/pre-commit
# Or create new hookcat > .git/hooks/commit-msg << 'EOF'#!/bin/bash# Validate commit message formatif ! grep -q "ISSUE-[0-9]\+:" "$1"; then echo "Commit message must include ISSUE-NNNN: format" exit 1fiEOFchmod +x .git/hooks/commit-msgGlobal Hook Configuration:
Section titled “Global Hook Configuration:”# Configure global hooks pathgit config --global core.hooksPath ~/.git-hooks
# Create global hooks directorymkdir ~/.git-hooks# Place hooks in ~/.git-hooks/Bypass Hook Execution:
Section titled “Bypass Hook Execution:”# Skip pre-commit and commit-msg hooksgit commit --no-verify -m "message"
# Environment variable methodGIT_EDITOR=true git commit --amend
# Skip hooks in scriptsexport GIT_COMMITTER_NAME="CI System"git commit -m "Automated commit"Hook Execution Environment:
Section titled “Hook Execution Environment:”Working Directory:
Section titled “Working Directory:”- Pre-receive/update/post-receive: Executed in
$GIT_DIR(bare repository) - All others: Executed in repository root (working directory for non-bare)
Available Environment Variables:
Section titled “Available Environment Variables:”# Always availableGIT_DIR # Path to .git directoryGIT_WORK_TREE # Path to working directory (when set)
# For push operationsGIT_PROTOCOL # Protocol used (http, ssh, etc.)GIT_PACKAGE_URL # Alternate Git server URL
# Custom environment detectionif [ -n "$CI" ] || [ -n "$CONTINUOUS_INTEGRATION" ]; then echo "Running in CI environment, adjust hook behavior"fiInput/Output Mechanisms:
Section titled “Input/Output Mechanisms:”# Standard input (for pre-receive/update)while read old_sha new_sha ref_name; do echo "Updating $ref_name: $old_sha -> $new_sha" # Validate changesdone
# Standard output (for messages)echo "Hook completed successfully"
# Exit codesexit 0 # Successexit 1 # Failure (reject operation)exit 65 # Hook not applicablePractical Hook Examples:
Section titled “Practical Hook Examples:”Pre-commit Quality Gates:
Section titled “Pre-commit Quality Gates:”#!/bin/bash# Run lintingif command -v eslint >/dev/null; then if ! eslint --ext .js,.jsx,.ts,.tsx .; then echo "ESLint failed. Fix issues before committing." exit 1 fifi
# Run testsif [ -f "package.json" ]; then npm test || exit 1fi
# Check for debug statementsif grep -r "console\.log\|debugger" --exclude-dir=node_modules .; then echo "Found debug statements. Remove before committing." exit 1fiCommit Message Enforcement:
Section titled “Commit Message Enforcement:”#!/bin/bashCOMMIT_MSG_FILE=$1COMMIT_MSG=$(cat $COMMIT_MSG_FILE)
# Check for minimum lengthif [ ${#COMMIT_MSG} -le 10 ]; then echo "Commit message too short. Minimum 10 characters." exit 1fi
# Check for issue number patternif ! echo "$COMMIT_MSG" | grep -q "ISSUE-[0-9]\+:"; then echo "Commit message must contain ISSUE-NNNN: pattern" exit 1fiServer-Side Access Control (pre-receive):
Section titled “Server-Side Access Control (pre-receive):”#!/bin/bashwhile read old_sha new_sha ref_name; do # Protect master branch if [ "$ref_name" = "refs/heads/master" ]; then echo "Direct pushes to master not allowed. Use pull requests." exit 1 fi
# Check user permissions for branch creation if [[ "$ref_name" =~ ^refs/heads/feature/ ]] && [[ -z "$old_sha" ]]; then # New branch creation logic echo "Creating feature branch: ${ref_name#refs/heads/feature/}" fidoneDeployment Automation (post-receive):
Section titled “Deployment Automation (post-receive):”#!/bin/bashwhile read old_sha new_sha ref_name; do if [ "$ref_name" = "refs/heads/master" ]; then echo "Deploying to production..." cd /path/to/deploy/dir
# Pull latest changes git pull origin master
# Restart services systemctl restart myapp systemctl reload nginx
echo "Deployment completed successfully" fidoneCommon Hook Patterns and Solutions:
Section titled “Common Hook Patterns and Solutions:”Linting and Testing Integration:
Section titled “Linting and Testing Integration:”#!/bin/bash# pre-commit - Run quality checks
STASH_NAME="pre-commit-$(date +%s)"if git diff --cached --name-only | grep -q .; then git stash push -q --keep-index -m "$STASH_NAME" STASHED=1fi
# Run checksnpm run lint || exit 1npm test || exit 1
if [ -n "$STASHED" ]; then git stash pop -qfiCode Review Gatekeeping:
Section titled “Code Review Gatekeeping:”#!/bin/bash# pre-receive - Enforce review requirements
while read old_sha new_sha ref_name; do # Skip checks for maintenance branches if [[ "$ref_name" =~ ^refs/heads/(main|develop|release/) ]]; then continue fi
# Check if commit has been reviewed # (Integration with external review system) review_status=$(curl -s "$REVIEW_API/commits/$new_sha") if [ "$review_status" != "approved" ]; then echo "Commit requires code review approval" exit 1 fidoneBranch Naming Standards:
Section titled “Branch Naming Standards:”#!/bin/bash# pre-receive - Enforce branch naming
while read old_sha new_sha ref_name; do if [[ "$ref_name" =~ ^refs/heads/ ]]; then branch_name=${ref_name#refs/heads/}
# Check naming pattern if ! [[ "$branch_name" =~ ^(feature|bugfix|hotfix)/.+ ]]; then echo "Branch name must start with feature/, bugfix/, or hotfix/" exit 1 fi fidoneNotifications and Integration:
Section titled “Notifications and Integration:”#!/bin/bash# post-receive - Send notifications
while read old_sha new_sha ref_name; do if [ "$ref_name" = "refs/heads/master" ]; then # Send notification to team curl -X POST -H 'Content-type: application/json' \ --data "{\"text\":\"Deployed to production: $new_sha\"}" \ "$SLACK_WEBHOOK_URL"
# Update monitoring curl "$MONITORING_API/deploy/$new_sha" fidoneHow do hooks differ from alias?
Section titled “How do hooks differ from alias?”Hooks run automatically at specified points; aliases require manual invocation. Hooks can prevent operations; aliases just provide shortcuts.
What’s the difference between pre-commit and commit-msg?
Section titled “What’s the difference between pre-commit and commit-msg?”pre-commit runs before commit creation, validates code. commit-msg runs after commit creation, validates the message format.
Can hooks be shared across team members?
Section titled “Can hooks be shared across team members?”Yes, but carefully - install in repository’s .git/hooks (get copied on clone) or globally via core.hooksPath configuration.
Why are my hooks not running during rebase?
Section titled “Why are my hooks not running during rebase?”Rebase uses internal operations that bypass some hooks. Use —no-verify during rebase if hooks cause issues.
What’s the safest way to test hook modifications?
Section titled “What’s the safest way to test hook modifications?”Test in a separate repository clone. Use git commit —no-verify initially. Make small incremental changes.
Can server hooks work with bare repositories?
Section titled “Can server hooks work with bare repositories?”Yes, server hooks (pre-receive, update, post-receive) are designed for bare repositories and run in $GIT_DIR.
How do I debug hook execution?
Section titled “How do I debug hook execution?”Add debugging output to hook scripts. Test manually with expected inputs. Use set -x in bash hooks for debugging.
What’s the performance impact of complex hooks?
Section titled “What’s the performance impact of complex hooks?”Heavy hooks can slow operations. Optimize with caching, move expensive checks to CI/CD, or run asynchronously where possible.
Can hooks access Git configuration?
Section titled “Can hooks access Git configuration?”Yes, hooks can run git config commands. Use —global or —local as appropriate for hook context.
How do I handle hooks during repository initialization?
Section titled “How do I handle hooks during repository initialization?”create .git/hooks directory during repo setup. Consider automated hook installation in project documentation.
What’s the relationship between hooks and CI/CD systems?
Section titled “What’s the relationship between hooks and CI/CD systems?”Hooks work locally; CI/CD executes on remote systems. Use hooks for pre-flight checks, CI/CD for comprehensive testing.
Can hooks be used for repository analytics?
Section titled “Can hooks be used for repository analytics?”Yes, post-commit and post-receive hooks can track changes, send metrics, and integrate with analytics systems.
How do I migrate hooks to different scripting languages?
Section titled “How do I migrate hooks to different scripting languages?”Rewrite in preferred language, keep execution logic same. Update shebang line. Test thoroughly.
What’s the impact of hook failures on team workflow?
Section titled “What’s the impact of hook failures on team workflow?”Failing hooks stop operations, so they’re great for policy but bad for workflow. Make hooks informative and provide bypass mechanisms.
Can hooks integrate with authentication systems?
Section titled “Can hooks integrate with authentication systems?”Yes, particularly server hooks. Use LDAP, OAuth, or custom authentication in pre-receive hooks with user context.
Applications of the Git hooks system
Section titled “Applications of the Git hooks system”- Code Quality Enforcement: Automatic linting, testing, and static analysis before commits
- Policy Compliance: Enforce commit message standards, branch naming conventions, and file organization
- Workflow Automation: Automatic deployment, notification systems, and integration with external tools
- Access Control: Server-side permission checks and branch protection in shared repositories
- Audit and Monitoring: Tracking repository usage, change metrics, and compliance reporting
- Integration Points: Connecting Git operations with project management, CI/CD, and development tools