Skip to content

Pre-Commit Hooks

Git Hooks

Git has hooks, which can run code on various events:

  • Prior to commiting code (pre-commit).
  • After committing code (post-commit).
  • After checking out a branch (post-checkout).
  • Before rebasing (pre-rebase).
  • Etc.

Pre-Commit Hook

  • Pre-commit Git hooks run checks before a commit is accepted.
  • Pre-commit is a package to automate the setup.
  • After config, issues such as syntax errors and security flaws are picked up.
  • Used mostly for formatting and linting.
  • Linting is checking code against a set of formatting rules and for syntax errors.

Pre-Commit (Python Tool)

  • Pre-commit is a Python tool for simplifying and applying Git pre-commit hooks.
  • Hooks can be configured via a YAML file, then applied on each attempted commit.
  • There are many hooks available from different sources.

Install it with:

pip install pre-commit

Add pre-commit-config.yaml

  • Add a pre-commit-config.yaml to your repo root.
  • A best practice config file, taken from FMTM:
repos:
  # Versioning: Commit messages & changelog
  - repo: https://github.com/commitizen-tools/commitizen
    rev: v3.28.0
    hooks:
      - id: commitizen
        stages: [commit-msg]

  # Lint / autoformat: Python code
  - repo: https://github.com/astral-sh/ruff-pre-commit
    # Ruff version.
    rev: "v0.5.4"
    hooks:
      # Run the linter
      - id: ruff
        args: [--fix, --exit-non-zero-on-fix]
      # Run the formatter
      - id: ruff-format

  # Autoformat: YAML, JSON, Markdown, etc.
  - repo: https://github.com/pycontribs/mirrors-prettier
    rev: v3.3.3
    hooks:
      - id: prettier
        args:
          [
            --ignore-unknown,
            --no-error-on-unmatched-pattern,
            "!CHANGELOG.md",
            "!CONTRIBUTING.md",
            "!src/frontend/pnpm-lock.yaml",
          ]

  # Lint: Bash scripts
  - repo: https://github.com/openstack-dev/bashate.git
    rev: 2.1.1
    hooks:
      - id: bashate

  # Lint: Shell scripts
  - repo: https://github.com/shellcheck-py/shellcheck-py
    rev: v0.9.0.6
    hooks:
      - id: shellcheck
        args: ["-x"]

  # Lint: Markdown
  - repo: https://github.com/igorshubovych/markdownlint-cli
    rev: v0.41.0
    hooks:
      - id: markdownlint
        args: [--fix, --ignore, CHANGELOG.md, --ignore, .github]

Note: the config above is for a monorepo configuration.

Your repo may not require both Python and JS code formatting.

Add Hooks

Run

# Standard install for most hooks
pre-commit install

# Additional commit-msg hook (for the commitizen hook above)
pre-commit install --hook-type commit-msg

Now when you attempt to commit to the repo:

  • Code will be auto-formatted.
  • An error will show if linting fails.
  • An error will show if commit messages are in the wrong format.