What is .pre-commit-config.yaml

Complete guide to pre-commit configuration files and Git hooks

Last updated: November 2024 9 min read

Introduction

The .pre-commit-config.yaml file is a configuration file used by the pre-commit framework. It defines a set of hooks that run automatically before each Git commit, helping maintain code quality, consistency, and preventing common mistakes.

What is Pre-commit?

Pre-commit is a framework for managing and maintaining multi-language pre-commit hooks. It allows you to run checks and formatters on your code before it's committed to your repository, ensuring code quality and consistency across your project.

Key Benefits

  • Automatically runs code quality checks before commits
  • Enforces coding standards and formatting
  • Catches errors early in the development process
  • Maintains consistency across team members
  • Supports multiple programming languages

File Structure

A basic .pre-commit-config.yaml file structure:

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

Key Components

  • repos - List of repositories containing hooks
  • repo - URL or local path to the hook repository
  • rev - Version/tag of the repository to use
  • hooks - List of hooks to run from the repository
  • id - Identifier of the specific hook

Common Pre-commit Hooks

Basic Hooks

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: trailing-whitespace      # Remove trailing whitespace
      - id: end-of-file-fixer        # Ensure files end with newline
      - id: check-yaml               # Validate YAML files
      - id: check-json               # Validate JSON files
      - id: check-added-large-files  # Prevent large files
      - id: check-merge-conflict     # Detect merge conflict markers
      - id: check-case-conflict      # Check for case conflicts
      - id: debug-statements         # Remove debug statements

Language-Specific Hooks

# Python hooks
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black

  - repo: https://github.com/pycqa/flake8
    rev: 6.0.0
    hooks:
      - id: flake8

# JavaScript/TypeScript hooks
  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v8.44.0
    hooks:
      - id: eslint

Complete Configuration Example

A comprehensive .pre-commit-config.yaml example:

# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
  # General file checks
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: check-added-large-files
        args: ['--maxkb=1000']
      - id: check-merge-conflict
      - id: check-case-conflict
      - id: mixed-line-ending
      - id: check-docstring-first

  # Python formatting and linting
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black
        language_version: python3

  - repo: https://github.com/pycqa/isort
    rev: 5.12.0
    hooks:
      - id: isort

  - repo: https://github.com/pycqa/flake8
    rev: 6.0.0
    hooks:
      - id: flake8
        args: ['--max-line-length=88', '--extend-ignore=E203']

  # YAML linting
  - repo: https://github.com/adrienverge/yamllint
    rev: v1.32.0
    hooks:
      - id: yamllint
        args: ['-d', '{extends: default, rules: {line-length: {max: 120}}}']

  # Markdown linting
  - repo: https://github.com/igorshubovych/markdownlint-cli
    rev: v0.35.0
    hooks:
      - id: markdownlint

Installation and Setup

Step 1: Install pre-commit

# Using pip
pip install pre-commit

# Using conda
conda install -c conda-forge pre-commit

# Using homebrew (macOS)
brew install pre-commit

Step 2: Create .pre-commit-config.yaml

Create the configuration file in your repository root:

# Create file in repository root
touch .pre-commit-config.yaml

# Add your hooks configuration (see examples above)

Step 3: Install Git hooks

# Install hooks into .git/hooks/
pre-commit install

# Install hooks for commit-msg
pre-commit install --hook-type commit-msg

# Install hooks for pre-push
pre-commit install --hook-type pre-push

Step 4: Test the hooks

# Run hooks on all files
pre-commit run --all-files

# Run a specific hook
pre-commit run trailing-whitespace --all-files

Advanced Configuration

Hook Arguments

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: check-added-large-files
        args: ['--maxkb=500']  # Custom arguments
      - id: trailing-whitespace
        args: ['--markdown-linebreak-ext=md']

File Filtering

repos:
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black
        files: ^src/  # Only run on files in src/
        exclude: ^tests/  # Exclude tests directory

Local Hooks

repos:
  - repo: local
    hooks:
      - id: custom-script
        name: Run custom script
        entry: bash scripts/check.sh
        language: system
        files: \.(py|js)$

Best Practices

  • Pin hook versions - Use specific version tags (rev) instead of branches
  • Start simple - Begin with basic hooks and add more as needed
  • Run on all files initially - Use pre-commit run --all-files to fix existing issues
  • Document custom hooks - Add comments explaining why specific hooks are used
  • Keep hooks fast - Avoid slow hooks that delay commits significantly

Troubleshooting

Issue: Hooks not running

Ensure hooks are installed:

# Reinstall hooks
pre-commit install

# Verify installation
ls .git/hooks/pre-commit

Issue: Skip hooks temporarily

Use --no-verify flag (use sparingly):

# Skip pre-commit hooks
git commit --no-verify -m "message"

# Note: This bypasses all hooks, use only when necessary

Related Articles