How to Install and Use Pre-commit on Ubuntu WSL 2

3 min read

Pre-commit is a framework that runs code checks automatically every time you commit. It catches formatting issues, trailing whitespace, syntax errors, and more — before bad code reaches your repository. This guide shows you how to install and use pre-commit on Ubuntu WSL 2.

The examples in this guide are run on WSL2 Ubuntu in Windows, but they work the same on any Ubuntu system.

Prerequisites

Install Pre-commit

The recommended way to install pre-commit is with pipx, which installs CLI tools in isolated environments so they don’t conflict with your project dependencies.

Option 1: Install with pipx (recommended)

If you don’t have pipx yet:

sudo apt update && sudo apt install -y pipx
pipx ensurepath

Restart your terminal, then install pre-commit:

pipx install pre-commit

Option 2: Install with pip

If you prefer pip:

pip install pre-commit

Verify the installation:

pre-commit --version

You should see something like pre-commit 4.5.1.

Create a Configuration File

Pre-commit uses a file called .pre-commit-config.yaml in the root of your repository. This file defines which hooks to run on each commit.

You can generate a starter config with:

pre-commit sample-config > .pre-commit-config.yaml

Or create one manually. Here’s a practical config for a Python project:

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: check-yaml
      - id: check-json
      - id: end-of-file-fixer
      - id: trailing-whitespace
      - id: check-merge-conflict

  - repo: https://github.com/psf/black
    rev: 26.1.0
    hooks:
      - id: black

The first repo provides general file checks. The second runs Black, the Python code formatter. The rev field pins each hook to a specific version.

If you use Ruff (a faster alternative to Black + Flake8), replace the Black block with:

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.5
    hooks:
      - id: ruff-check
      - id: ruff-format

Install the Git Hooks

Once your config file is ready, install the hooks into your Git repository:

pre-commit install

This creates a .git/hooks/pre-commit script that triggers the configured checks every time you run git commit.

Run Pre-commit

After installing, hooks run automatically on staged files when you commit. The first run downloads the hook environments, which takes a few seconds.

To run all hooks against every file in the repo (useful when adding pre-commit to an existing project):

pre-commit run --all-files

To run hooks against specific files only:

pre-commit run --files src/main.py src/utils.py

If a hook fails, it either fixes the file automatically (like Black reformatting code) or reports what needs to change. Fix the issues, re-stage the files with git add, and commit again.

Keep Hooks Updated

Hook versions in your config are pinned. To update all hooks to their latest versions:

pre-commit autoupdate

This updates the rev values in .pre-commit-config.yaml to the latest tags. Run this periodically and commit the updated config file.

Skip Hooks When Needed

Sometimes you need to commit without running hooks (for example, a work-in-progress commit). Use the --no-verify flag:

git commit --no-verify -m "WIP: work in progress"

To skip a specific hook instead of all of them, use the SKIP environment variable:

SKIP=black git commit -m "skip formatting for now"

Use these sparingly — the point of pre-commit is to catch issues before they reach the repository.

Conclusion

Pre-commit keeps your repository clean by running checks automatically on every commit. Install it once, add a config file, and it handles the rest. For Python-specific formatting and linting, see How to Use Flake8 and Black for Python Code Quality and Style Consistency. If you’re setting up your WSL development environment, check out How to Connect Visual Studio Code with WSL 2 for Linux Ubuntu.