Git Hooks for Code Quality: Pre-Commit, Pre-Push, and Beyond
Git hooks automate code quality checks at commit and push time, catching issues before they enter the codebase. This guide covers setting up linting, formatting, type checking, and test hooks with practical examples.
Key Takeaways
- Without automated checks, code quality depends entirely on developer discipline and code review.
- Runs before a commit is created.
- The `pre-commit` framework (pre-commit.com) manages hooks declaratively via a `.pre-commit-config.yaml` file:
- Add a secret detection hook to prevent accidental commits of API keys, passwords, and tokens.
- Hooks are local to each developer's machine — they're not automatically shared via Git.
What Git Hooks Solve
Without automated checks, code quality depends entirely on developer discipline and code review. Git hooks add an automated layer: linting runs before every commit, tests run before every push, and formatting is enforced consistently. Issues are caught in seconds on the developer's machine rather than minutes later in CI.
Hook Types
pre-commit
Runs before a commit is created. If the hook exits with a non-zero status, the commit is aborted. This is the most commonly used hook.
Best for: Linting, formatting, type checking, secret detection, file size limits, and trailing whitespace removal.
pre-push
Runs before git push sends data to the remote. Use for checks that are too slow for pre-commit but should catch issues before they reach the team.
Best for: Running the full test suite, integration tests, build verification.
commit-msg
Validates the commit message format. Useful for enforcing conventional commit messages (feat:, fix:, docs:) that enable automated changelog generation.
Setting Up Pre-Commit Hooks
The pre-commit Framework
The pre-commit framework (pre-commit.com) manages hooks declaratively via a .pre-commit-config.yaml file:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
args: ['--maxkb=500']
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
Speed Optimization
Pre-commit hooks should complete in under 5 seconds. Slow hooks frustrate developers and get bypassed with --no-verify. Only check staged files (not the entire codebase), use incremental checking tools, and skip expensive operations (full test suites belong in pre-push or CI).
Secret Detection
Add a secret detection hook to prevent accidental commits of API keys, passwords, and tokens. Tools like detect-secrets and gitleaks scan staged files for patterns matching common secret formats (AWS keys, JWT tokens, private keys).
Team Adoption
Hooks are local to each developer's machine — they're not automatically shared via Git. Use the pre-commit framework with pre-commit install in your onboarding documentation, or configure your package manager to install hooks automatically (npm prepare script, uv post-install hook).