Skip to content

Git — Hooks & Configuration

Git Hooks Overview

Scripts that Git executes automatically at specific points in the workflow.

Hook Trigger Common Use
pre-commit Before commit is created Lint, format, type-check staged files
commit-msg After message is entered Validate Conventional Commit format
prepare-commit-msg Before editor opens Prepend ticket ID to message
pre-push Before push to remote Run tests, check branch rules
post-merge After merge completes Install deps if lockfile changed
post-checkout After branch switch Run migrations, clear caches

Client-Side vs Server-Side

Side Hooks Enforcement
Client pre-commit, commit-msg, pre-push Can be bypassed with --no-verify
Server pre-receive, update, post-receive Cannot be bypassed — ultimate gate

Hook Setup with pre-commit

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-added-large-files

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.9.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.14.0
    hooks:
      - id: mypy
pip install pre-commit                         # Or: uv tool install pre-commit
pre-commit install                             # Install hooks into .git/hooks/
pre-commit run --all-files                     # Run on entire repo
pre-commit autoupdate                          # Update hook versions

Native Git Hooks (No Framework)

git config --local core.hooksPath .githooks    # Point to tracked directory (local repo scope)
#!/bin/sh
# .githooks/pre-commit
echo "Running pre-commit checks..."
ruff check . && ruff format --check .
chmod +x .githooks/pre-commit

.gitignore

Structure

# Dependencies
.venv/
__pycache__/

# Build output
dist/
build/
*.egg-info/

# Environment & secrets
.env
.env.*
!.env.example
secrets/

# IDE
.vscode/
.idea/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Testing / coverage
coverage/
htmlcov/
.pytest_cache/
.mypy_cache/
.ruff_cache/

# Logs
*.log
logs/

Patterns

Pattern Matches
*.log All .log files everywhere
/build Only build/ in root
build/ Any build/ at any depth
!important.log Exclude from ignore (negate)
doc/**/*.pdf PDFs in doc/ tree

Global Gitignore

git config --global core.excludesFile ~/.gitignore_global
# Add OS/IDE patterns (.DS_Store, Thumbs.db, .vscode/, .idea/) there

Git Aliases

git config --global alias.st "status -s"
git config --global alias.co "checkout"
git config --global alias.sw "switch"
git config --global alias.br "branch -v"
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.last "log -1 --stat"
git config --global alias.unstage "reset HEAD --"
git config --global alias.amend "commit --amend --no-edit"
git config --global alias.wip "commit -am 'WIP'"
git config --global init.defaultBranch main
git config --global pull.rebase true           # Rebase on pull (linear history)
git config --global push.default current       # Push current branch by name
git config --global push.autoSetupRemote true  # Auto set upstream on first push
git config --global fetch.prune true           # Auto prune on fetch
git config --global rerere.enabled true        # Remember conflict resolutions
git config --global diff.algorithm histogram   # Better diff output
git config --global merge.conflictStyle zdiff3 # Show base in conflict markers
git config --global core.autocrlf input        # LF everywhere (Linux/Mac)

Verify Configuration

git config --list --show-origin                # All settings with source file
git config --global --list                     # Global settings only
git config user.name                           # Single value