◐ Shell
reader mode source ↗

pre-commit

A framework for managing and maintaining multi-language pre-commit hooks.

pre-commit logo

Git hook scripts are useful for identifying simple issues before submission to code review. We run our hooks on every commit to automatically point out issues in code such as missing semicolons, trailing whitespace, and debug statements. By pointing these issues out before code review, this allows a code reviewer to focus on the architecture of a change while not wasting time with trivial style nitpicks.

As we created more libraries and projects we recognized that sharing our pre-commit hooks across projects is painful. We copied and pasted unwieldy bash scripts from project to project and had to manually change the hooks to work for different project structures.

We believe that you should always use the best industry standard linters. Some of the best linters are written in languages that you do not use in your project or have installed on your machine. For example scss-lint is a linter for SCSS written in Ruby. If you’re writing a project in node you should be able to use scss-lint as a pre-commit hook without adding a Gemfile to your project or understanding how to get scss-lint installed.

We built pre-commit to solve our hook issues. It is a multi-language package manager for pre-commit hooks. You specify a list of hooks you want and pre-commit manages the installation and execution of any hook written in any language before every commit. pre-commit is specifically designed to not require root access. If one of your developers doesn’t have node installed but modifies a JavaScript file, pre-commit automatically handles downloading and building node to run eslint without root.

Before you can run hooks, you need to have the pre-commit package manager installed.

Using pip:

pip install pre-commit

In a python project, add the following to your requirements.txt (or requirements-dev.txt):

pre-commit

As a 0-dependency zipapp:

  • locate and download the .pyz file from the github releases
  • run python pre-commit-#.#.#.pyz ... in place of pre-commit ...

Quick start

1. Install pre-commit

  • follow the install instructions above
  • pre-commit --version should show you what version you're using
$ pre-commit --version
pre-commit 4.6.0
  • create a file named .pre-commit-config.yaml
  • you can generate a very basic configuration using pre-commit sample-config
  • the full set of options for the configuration are listed below
  • this example uses a formatter for python code, however pre-commit works for any programming language
  • other supported hooks are available
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.3.0
    hooks:
    -   id: check-yaml
    -   id: end-of-file-fixer
    -   id: trailing-whitespace
-   repo: https://github.com/psf/black
    rev: 22.10.0
    hooks:
    -   id: black

3. Install the git hook scripts

  • run pre-commit install to set up the git hook scripts
$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
  • now pre-commit will run automatically on git commit!

4. (optional) Run against all the files

  • it's usually a good idea to run the hooks against all of the files when adding new hooks (usually pre-commit will only run on the changed files during git hooks)
$ pre-commit run --all-files
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Initializing environment for https://github.com/psf/black.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/psf/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
Check Yaml...............................................................Passed
Fix End of Files.........................................................Passed
Trim Trailing Whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1

Files were modified by this hook. Additional output:

Fixing sample.py

black....................................................................Passed
  • oops! looks like I had some trailing whitespace
  • consider running that in CI too

Once you have pre-commit installed, adding pre-commit plugins to your project is done with the .pre-commit-config.yaml configuration file.

Add a file called .pre-commit-config.yaml to the root of your project. The pre-commit config file describes what repositories and hooks are installed.

.pre-commit-config.yaml - top level

repos

A list of repository mappings.

default_install_hook_types

(optional: default [pre-commit]) a list of --hook-types which will be used by default when running pre-commit install.

default_language_version

(optional: default {}) a mapping from language to the default language_version that should be used for that language. This will only override individual hooks that do not set language_version.

For example to use python3.7 for language: python hooks:

default_language_version:
    python: python3.7

default_stages

(optional: default (all stages)) a configuration-wide default for the stages property of hooks. This will only override individual hooks that do not set stages.

For example:

default_stages: [pre-commit, pre-push]

files

(optional: default '') global file include pattern.

exclude

(optional: default ^$) global file exclude pattern.

fail_fast

(optional: default false) set to true to have pre-commit stop running hooks after the first failure.

minimum_pre_commit_version

(optional: default '0') require a minimum version of pre-commit.

A sample top-level:

exclude: '^$'
fail_fast: false
repos:
-   ...

.pre-commit-config.yaml - repos

The repository mapping tells pre-commit where to get the code for the hook from.

repo

the repository url to git clone from or one of the special sentinel values: local, meta.

rev

the revision or tag to clone at.

hooks

A list of hook mappings.

A sample repository:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v1.2.3
    hooks:
    -   ...

.pre-commit-config.yaml - hooks

The hook mapping configures which hook from the repository is used and allows for customization. All optional keys will receive their default from the repository's configuration.

id

which hook from the repository to use.

alias

(optional) allows the hook to be referenced using an additional id when using pre-commit run <hookid>.

name

(optional) override the name of the hook - shown during hook execution.

language_version

(optional) override the language version for the hook. See Overriding Language Version.

files

(optional) override the default pattern for files to run on.

exclude

(optional) file exclude pattern.

types

(optional) override the default file types to run on (AND). See Filtering files with types.

types_or

(optional) override the default file types to run on (OR). See Filtering files with types.

exclude_types

(optional) file types to exclude.

args

(optional) list of additional parameters to pass to the hook.

stages

(optional) selects which git hook(s) to run for. See Confining hooks to run at certain stages.

(optional) a list of dependencies that will be installed in the environment where this hook gets run. One useful application is to install plugins for hooks such as eslint.

always_run

(optional) if true, this hook will run even if there are no matching files.

verbose

(optional) if true, forces the output of the hook to be printed even when the hook passes.

log_file

(optional) if present, the hook output will additionally be written to a file when the hook fails or verbose is true.

One example of a complete configuration:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v1.2.3
    hooks:
    -   id: trailing-whitespace

This configuration says to download the pre-commit-hooks project and run its trailing-whitespace hook.

Updating hooks automatically

You can update your hooks to the latest version automatically by running pre-commit autoupdate. By default, this will bring the hooks to the latest tag on the default branch.

Run pre-commit install to install pre-commit into your git hooks. pre-commit will now run on every commit. Every time you clone a project using pre-commit running pre-commit install should always be the first thing you do.

If you want to manually run all pre-commit hooks on a repository, run pre-commit run --all-files. To run individual hooks use pre-commit run <hook_id>.

The first time pre-commit runs on a file it will automatically download, install, and run the hook. Note that running a hook for the first time may be slow. For example: If the machine does not have node installed, pre-commit will download and build a copy of node.

$ pre-commit install
pre-commit installed at /home/asottile/workspace/pytest/.git/hooks/pre-commit
$ git commit -m "Add super awesome feature"
black....................................................................Passed
blacken-docs.........................................(no files to check)Skipped
Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Passed
Check Yaml...........................................(no files to check)Skipped
Debug Statements (Python)................................................Passed
Flake8...................................................................Passed
Reorder python imports...................................................Passed
pyupgrade................................................................Passed
rst ``code`` is two backticks........................(no files to check)Skipped
rst..................................................(no files to check)Skipped
changelog filenames..................................(no files to check)Skipped
[main 146c6c2c] Add super awesome feature
 1 file changed, 1 insertion(+)

pre-commit currently supports hooks written in many languages. As long as your git repo is an installable package (gem, npm, pypi, etc.) or exposes an executable, it can be used with pre-commit. Each git repo can support as many languages/hooks as you want.

new in 2.5.0: pre-commit sets the PRE_COMMIT=1 environment variable during hook execution.

The hook must exit nonzero on failure or modify files.

A git repo containing pre-commit plugins must contain a .pre-commit-hooks.yaml file that tells pre-commit:

id

the id of the hook - used in pre-commit-config.yaml.

name

the name of the hook - shown during hook execution.

entry

the entry point - the executable to run. entry can also contain arguments that will not be overridden such as entry: autopep8 -i.

language

the language of the hook - tells pre-commit how to install the hook.

files

(optional: default '') the pattern of files to run on.

exclude

(optional: default ^$) exclude files that were matched by files.

types

(optional: default [file]) list of file types to run on (AND). See Filtering files with types.

types_or

(optional: default []) list of file types to run on (OR). See Filtering files with types.

exclude_types

(optional: default []) the pattern of files to exclude.

always_run

(optional: default false) if true this hook will run even if there are no matching files.

fail_fast

(optional: default false) if true pre-commit will stop running hooks if this hook fails.

verbose

(optional: default false) if true, forces the output of the hook to be printed even when the hook passes.

pass_filenames

(optional: default true) if false no filenames will be passed to the hook.

require_serial

(optional: default false) if true this hook will execute using a single process instead of in parallel.

description

(optional: default '') description of the hook. used for metadata purposes only.

language_version

(optional: default default) see Overriding language version.

minimum_pre_commit_version

(optional: default '0') allows one to indicate a minimum compatible pre-commit version.

args

(optional: default []) list of additional parameters to pass to the hook.

stages

(optional: default (all stages)) selects which git hook(s) to run for. See Confining hooks to run at certain stages.

For example:

-   id: trailing-whitespace
    name: Trim Trailing Whitespace
    description: This hook trims trailing whitespace.
    entry: trailing-whitespace-fixer
    language: python
    types: [text]

Developing hooks interactively

Since the repo property of .pre-commit-config.yaml can refer to anything that git clone ... understands, it's often useful to point it at a local directory while developing hooks.

pre-commit try-repo streamlines this process by enabling a quick way to try out a repository. Here's how one might work interactively:

note: you may need to provide --commit-msg-filename when using this command with hook types prepare-commit-msg and commit-msg.

a commit is not necessary to try-repo on a local directory. pre-commit will clone any tracked uncommitted changes.

~/work/hook-repo $ git checkout origin/main -b feature

# ... make some changes

# In another terminal or tab

~/work/other-repo $ pre-commit try-repo ../hook-repo foo --verbose --all-files
===============================================================================
Using config:
===============================================================================
repos:
-   repo: ../hook-repo
    rev: 84f01ac09fcd8610824f9626a590b83cfae9bcbd
    hooks:
    -   id: foo
===============================================================================
[INFO] Initializing environment for ../hook-repo.
Foo......................................................................Passed
- hook id: foo
- duration: 0.02s

Hello from foo hook!

Supported languages

conda

The hook repository must contain an environment.yml file which will be used via conda env create --file environment.yml ... to create the environment.

The conda language also supports additional_dependencies and will pass any of the values directly into conda install. This language can therefore be used with local hooks.

mamba or micromamba can be used to install instead via the PRE_COMMIT_USE_MAMBA=1 or PRE_COMMIT_USE_MICROMAMBA=1 environment variables.

Support: conda hooks work as long as there is a system-installed conda binary (such as miniconda). It has been tested on linux, macOS, and windows.

coursier

The hook repository must have a .pre-commit-channel folder and that folder must contain the coursier application descriptors for the hook to install. For configuring coursier hooks, your entry should correspond to an executable installed from the repository's .pre-commit-channel folder.

Support: coursier hooks are known to work on any system which has the cs or coursier package manager installed. The specific coursier applications you install may depend on various versions of the JVM, consult the hooks' documentation for clarification. It has been tested on linux.

pre-commit also supports the coursier naming of the package manager executable.

new in 3.0.0: language: coursier hooks now support repo: local and additional_dependencies.

dart

The hook repository must have a pubspec.yaml -- this must contain an executables section which will list the binaries that will be available after installation. Match the entry to an executable.

pre-commit will build each executable using dart compile exe bin/{executable}.dart.

language: dart also supports additional_dependencies. to specify a version for a dependency, separate the package name by a ::

        additional_dependencies: ['hello_world_dart:1.0.0']

Support: dart hooks are known to work on any system which has the dart sdk installed. It has been tested on linux, macOS, and windows.

docker

The hook repository must have a Dockerfile. It will be installed via docker build ..

Running Docker hooks requires a running Docker engine on your host. For configuring Docker hooks, your entry should correspond to an executable inside the Docker container, and will be used to override the default container entrypoint. Your Docker CMD will not run when pre-commit passes a file list as arguments to the run container command. Docker allows you to use any language that's not supported by pre-commit as a builtin.

pre-commit will automatically mount the repository source as a volume using -v $PWD:/src:rw,Z and set the working directory using --workdir /src.

Support: docker hooks are known to work on any system which has a working docker executable. It has been tested on linux and macOS. Hooks that are run via boot2docker are known to be unable to make modifications to files.

See this repository for an example Docker-based hook.

docker_image

A more lightweight approach to docker hooks. The docker_image "language" uses existing docker images to provide hook executables.

docker_image hooks can be conveniently configured as local hooks.

The entry specifies the docker tag to use. If an image has an ENTRYPOINT defined, nothing special is needed to hook up the executable. If the container does not specify an ENTRYPOINT or you want to change the entrypoint you can specify it as well in your entry.

For example:

-   id: dockerfile-provides-entrypoint
    name: ...
    language: docker_image
    entry: my.registry.example.com/docker-image-1:latest
-   id: dockerfile-no-entrypoint-1
    name: ...
    language: docker_image
    entry: --entrypoint my-exe my.registry.example.com/docker-image-2:latest
# Alternative equivalent solution
-   id: dockerfile-no-entrypoint-2
    name: ...
    language: docker_image
    entry: my.registry.example.com/docker-image-3:latest my-exe

dotnet

dotnet hooks are installed using the system installation of the dotnet CLI.

Hook repositories must contain a dotnet CLI tool which can be packed and installed as per this example. The entry should match an executable created by building the repository. Additional dependencies are not currently supported.

Support: dotnet hooks are known to work on any system which has the dotnet CLI installed. It has been tested on linux and windows.

fail

A lightweight language to forbid files by filename. The fail language is especially useful for local hooks.

The entry will be printed when the hook fails. It is suggested to provide a brief description for name and more verbose fix instructions in entry.

Here's an example which prevents any file except those ending with .rst from being added to the changelog directory:

-   repo: local
    hooks:
    -   id: changelogs-rst
        name: changelogs must be rst
        entry: changelog filenames must end in .rst
        language: fail
        files: 'changelog/.*(?<!\.rst)$'

golang

The hook repository must contain go source code. It will be installed via go install ./.... pre-commit will create an isolated GOPATH for each hook and the entry should match an executable which will get installed into the GOPATH's bin directory.

This language supports additional_dependencies and will pass any of the values directly to go install. It can be used as a repo: local hook.

changed in 2.17.0: previously go get ./... was used

new in 3.0.0: pre-commit will bootstrap go if it is not present. language: golang also now supports language_version

Support: golang hooks are known to work on any system which has go installed. It has been tested on linux, macOS, and windows.

haskell

new in 3.4.0

The hook repository must have one or more *.cabal files. Once installed the executables from these packages will be available to use with entry.

This language supports additional_dependencies so it can be used as a repo: local hook.

Support: haskell hooks are known to work on any system which has cabal installed. It has been tested on linux, macOS, and windows.

julia

new in 4.1.0

For configuring julia hooks, your entry should be a path to a julia source file relative to the hook repository (optionally with arguments).

Hooks run in an isolated package environment defined by a Project.toml file (optionally with a Manifest.toml file) in the hook repository. If no Project.toml file is found the hook is run in an empty environment.

Julia hooks support additional_dependencies which can be used to augment, or override, the existing environment in the hooks repository. This also means that julia can be used as a repo: local hook. additional_dependencies are passed to pkg> add and should be specified using Pkg REPL mode syntax.

Examples:

- id: foo-without-args
  name: ...
  language: julia
  entry: bin/foo.jl
- id: bar-with-args
  name: ...
  language: julia
  entry: bin/bar.jl --arg1 --arg2
- id: baz-with-extra-deps
  name: ...
  language: julia
  entry: bin/baz.jl
  additional_dependencies:
   - 'ExtraDepA@1'
   - '[email protected]'

Support: julia hooks are known to work on any system which has julia installed.

lua

Lua hooks are installed with the version of Lua that is used by Luarocks.

Support: Lua hooks are known to work on any system which has Luarocks installed. It has been tested on linux and macOS and may work on windows.

node

The hook repository must have a package.json. It will be installed via npm install .. The installed package will provide an executable that will match the entry – usually through bin in package.json.

Support: node hooks work without any system-level dependencies. It has been tested on linux, windows, and macOS and may work under cygwin.

perl

Perl hooks are installed using the system installation of cpan, the CPAN package installer that comes with Perl.

Hook repositories must have something that cpan supports, typically Makefile.PL or Build.PL, which it uses to install an executable to use in the entry definition for your hook. The repository will be installed via cpan -T . (with the installed files stored in your pre-commit cache, not polluting other Perl installations).

When specifying additional_dependencies for Perl, you can use any of the install argument formats understood by cpan.

Support: Perl hooks currently require a pre-existing Perl installation, including the cpan tool in PATH. It has been tested on linux, macOS, and Windows.

python

The hook repository must be installable via pip install . (usually by either setup.py or pyproject.toml). The installed package will provide an executable that will match the entry – usually through console_scripts or scripts in setup.py.

This language also supports additional_dependencies so it can be used with local hooks. The specified dependencies will be appended to the pip install command.

Support: python hooks work without any system-level dependencies. It has been tested on linux, macOS, windows, and cygwin.

r

This hook repository must have a renv.lock file that will be restored with renv::restore() on hook installation. If the repository is an R package (i.e. has Type: Package in DESCRIPTION), it is installed. The supported syntax in entry is Rscript -e {expression} or Rscript path/relative/to/hook/root. The R Startup process is skipped (emulating --vanilla), as all configuration should be exposed via args for maximal transparency and portability.

When specifying additional_dependencies for R, you can use any of the install argument formats understood by renv::install().

Support: r hooks work as long as R is installed and on PATH. It has been tested on linux, macOS, and windows.

ruby

The hook repository must have a *.gemspec. It will be installed via gem build *.gemspec && gem install *.gem. The installed package will produce an executable that will match the entry – usually through executables in your gemspec.

Support: ruby hooks work without any system-level dependencies. It has been tested on linux and macOS and may work under cygwin.

rust

Rust hooks are installed using Cargo, Rust's official package manager.

Hook repositories must have a Cargo.toml file which produces at least one binary (example), whose name should match the entry definition for your hook. The repo will be installed via cargo install --bins (with the binaries stored in your pre-commit cache, not polluting your user-level Cargo installations).

When specifying additional_dependencies for Rust, you can use the syntax {package_name}:{package_version} to specify a new library dependency (used to build your hook repo), or the special syntax cli:{package_name}:{package_version} for a CLI dependency (built separately, with binaries made available for use by hooks).

pre-commit will bootstrap rust if it is not present. language: rust also supports language_version

Support: It has been tested on linux, Windows, and macOS.

swift

The hook repository must have a Package.swift. It will be installed via swift build -c release. The entry should match an executable created by building the repository.

Support: swift hooks are known to work on any system which has swift installed. It has been tested on linux and macOS.

pygrep

A cross-platform python implementation of grep – pygrep hooks are a quick way to write a simple hook which prevents commits by file matching. Specify the regex as the entry. The entry may be any python regular expression. For case insensitive regexes you can apply the (?i) flag as the start of your entry, or use args: [-i].

For multiline matches, use args: [--multiline].

To require all files to match, use args: [--negate].

Support: pygrep hooks are supported on all platforms which pre-commit runs on.

unsupported

new in 4.4.0: previously language: system. the alias will be removed in a future version

System hooks provide a way to write hooks for system-level executables which don't have a supported language above (or have special environment requirements that don't allow them to run in isolation such as pylint).

This hook type will not be given a virtual environment to work with – if it needs additional dependencies the consumer must install them manually.

unsupported_script

new in 4.4.0: previously language: script. the alias will be removed in a future version

Script hooks provide a way to write simple scripts which validate files. The entry should be a path relative to the root of the hook repository.

This hook type will not be given a virtual environment to work with – if it needs additional dependencies the consumer must install them manually.

All pre-commit commands take the following options:

  • --color {auto,always,never}: whether to use color in output. Defaults to auto. can be overridden by using PRE_COMMIT_COLOR={auto,always,never} or disabled using TERM=dumb.
  • -c CONFIG, --config CONFIG: path to alternate config file
  • -h, --help: show help and available options.

pre-commit exits with specific codes:

  • 1: a detected / expected error
  • 3: an unexpected error
  • 130: the process was interrupted by ^C

pre-commit autoupdate [options]

Auto-update pre-commit config to the latest repos' versions.

Options:

  • --bleeding-edge: update to the bleeding edge of the default branch instead of the latest tagged version (the default behaviour).
  • --freeze: Store "frozen" hashes in rev instead of tag names.
  • --repo REPO: Only update this repository. This option may be specified multiple times.
  • -j / --jobs: new in 3.3.0 Number of threads to use (default: 1).

Here are some sample invocations using this .pre-commit-config.yaml:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.1.0
    hooks:
    -   id: trailing-whitespace
-   repo: https://github.com/asottile/pyupgrade
    rev: v1.25.0
    hooks:
    -   id: pyupgrade
        args: [--py36-plus]
$ : default: update to latest tag on default branch
$ pre-commit autoupdate  # by default: pick tags
Updating https://github.com/pre-commit/pre-commit-hooks ... updating v2.1.0 -> v2.4.0.
Updating https://github.com/asottile/pyupgrade ... updating v1.25.0 -> v1.25.2.
$ grep rev: .pre-commit-config.yaml
    rev: v2.4.0
    rev: v1.25.2
$ : update a specific repository to the latest revision of the default branch
$ pre-commit autoupdate --bleeding-edge --repo https://github.com/pre-commit/pre-commit-hooks
Updating https://github.com/pre-commit/pre-commit-hooks ... updating v2.1.0 -> 5df1a4bf6f04a1ed3a643167b38d502575e29aef.
$ grep rev: .pre-commit-config.yaml
    rev: 5df1a4bf6f04a1ed3a643167b38d502575e29aef
    rev: v1.25.0
$ : update to frozen versions
$ pre-commit autoupdate --freeze
Updating https://github.com/pre-commit/pre-commit-hooks ... updating v2.1.0 -> v2.4.0 (frozen).
Updating https://github.com/asottile/pyupgrade ... updating v1.25.0 -> v1.25.2 (frozen).
$ grep rev: .pre-commit-config.yaml
    rev: 0161422b4e09b47536ea13f49e786eb3616fe0d7  # frozen: v2.4.0
    rev: 34a269fd7650d264e4de7603157c10d0a9bb8211  # frozen: v1.25.2

pre-commit will preferentially pick tags containing a . if there are ties.

pre-commit clean [options]

Clean out cached pre-commit files.

Options: (no additional options)

pre-commit gc [options]

Clean unused cached repos.

pre-commit keeps a cache of installed hook repositories which grows over time. This command can be run periodically to clean out unused repos from the cache directory.

Options: (no additional options)

pre-commit init-templatedir DIRECTORY [options]

Install hook script in a directory intended for use with git config init.templateDir.

Options:

  • -t HOOK_TYPE, --hook-type HOOK_TYPE: which hook type to install.

Some example useful invocations:

git config --global init.templateDir ~/.git-template
pre-commit init-templatedir ~/.git-template

For Windows cmd.exe use %HOMEPATH% instead of ~:

pre-commit init-templatedir %HOMEPATH%\.git-template

For Windows PowerShell use $HOME instead of ~:

pre-commit init-templatedir $HOME\.git-template

Now whenever a repository is cloned or created, it will have the hooks set up already!

pre-commit install [options]

Install the pre-commit script.

Options:

  • -f, --overwrite: Replace any existing git hooks with the pre-commit script.
  • --install-hooks: Also install environments for all available hooks now (rather than when they are first executed). See pre-commit install-hooks.
  • -t HOOK_TYPE, --hook-type HOOK_TYPE: Specify which hook type to install.
  • --allow-missing-config: Hook scripts will permit a missing configuration file.

Some example useful invocations:

  • pre-commit install: Default invocation. Installs the hook scripts alongside any existing git hooks.
  • pre-commit install --install-hooks --overwrite: Idempotently replaces existing git hook scripts with pre-commit, and also installs hook environments.

pre-commit install will install hooks from default_install_hook_types if --hook-type is not specified on the command line.

pre-commit install-hooks [options]

Install all missing environments for the available hooks. Unless this command or install --install-hooks is executed, each hook's environment is created the first time the hook is called.

Each hook is initialized in a separate environment appropriate to the language the hook is written in. See supported languages.

This command does not install the pre-commit script. To install the script along with the hook environments in one command, use pre-commit install --install-hooks.

Options: (no additional options)

pre-commit migrate-config [options]

Migrate list configuration to the new map configuration format.

Options: (no additional options)

pre-commit run [hook-id] [options]

Run hooks.

Options:

  • [hook-id]: specify a single hook-id to run only that hook.
  • -a, --all-files: run on all the files in the repo.
  • --files [FILES [FILES ...]]: specific filenames to run hooks on.
  • --from-ref FROM_REF + --to-ref TO_REF: run against the files changed between FROM_REF...TO_REF in git.
  • --hook-stage STAGE: select a stage to run.
  • --show-diff-on-failure: when hooks fail, run git diff directly afterward.
  • -v, --verbose: produce hook output independent of success. Include hook ids in output.

Some example useful invocations:

  • pre-commit run: this is what pre-commit runs by default when committing. This will run all hooks against currently staged files.
  • pre-commit run --all-files: run all the hooks against all the files. This is a useful invocation if you are using pre-commit in CI.
  • pre-commit run flake8: run the flake8 hook against all staged files.
  • git ls-files -- '*.py' | xargs pre-commit run --files: run all hooks against all *.py files in the repository.
  • pre-commit run --from-ref HEAD^^^ --to-ref HEAD: run against the files that have changed between HEAD^^^ and HEAD. This form is useful when leveraged in a pre-receive hook.

pre-commit sample-config [options]

Produce a sample .pre-commit-config.yaml.

Options: (no additional options)

pre-commit try-repo REPO [options]

Try the hooks in a repository, useful for developing new hooks. try-repo can also be used for testing out a repository before adding it to your configuration. try-repo prints a configuration it generates based on the remote hook repository before running the hooks.

Options:

  • REPO: required clonable hooks repository. Can be a local path on disk.
  • --ref REF: Manually select a ref to run against, otherwise the HEAD revision will be used.
  • pre-commit try-repo also supports all available options for pre-commit run.

Some example useful invocations:

  • pre-commit try-repo https://github.com/pre-commit/pre-commit-hooks: runs all the hooks in the latest revision of pre-commit/pre-commit-hooks.
  • pre-commit try-repo ../path/to/repo: run all the hooks in a repository on disk.
  • pre-commit try-repo ../pre-commit-hooks flake8: run only the flake8 hook configured in a local ../pre-commit-hooks repository.
  • See pre-commit run for more useful run invocations which are also supported by pre-commit try-repo.

pre-commit uninstall [options]

Uninstall the pre-commit script.

Options:

  • -t HOOK_TYPE, --hook-type HOOK_TYPE: which hook type to uninstall.

pre-commit validate-config [options] [filenames ...]

Validate .pre-commit-config.yaml files

pre-commit validate-manifest [options] [filenames ...]

Validate .pre-commit-hooks.yaml files

We’re looking to grow the project and get more contributors especially to support more languages/versions. We’d also like to get the .pre-commit-hooks.yaml files added to popular linters without maintaining forks / mirrors.

Feel free to submit bug reports, pull requests, and feature requests.

Sponsoring

If you or your company would like to support the development of pre-commit one can contribute in the following ways:

Getting help

There are several ways to get help for pre-commit:

Contributors