pre-commit 钩子

一个用于管理和维护多语言 pre-commit 钩子的框架。

Star
pre-commit logo

Git 钩子脚本对于在提交代码审查之前识别简单问题非常有用。我们在每次提交时都运行我们的钩子,以自动指出代码中的问题,例如缺少分号、尾随空格和调试语句。通过在代码审查之前指出这些问题,这允许代码审查者专注于更改的架构,而不必浪费时间处理琐碎的样式挑剔。

随着我们创建了更多库和项目,我们意识到在项目之间共享我们的 pre-commit 钩子非常痛苦。我们从一个项目复制粘贴笨重的 bash 脚本到另一个项目,并且必须手动更改钩子以适应不同的项目结构。

我们认为您应该始终使用最佳的行业标准 linter。一些最好的 linter 是用您在项目中未使用或未安装在机器上的语言编写的。例如,scss-lint 是一个用 Ruby 编写的 SCSS linter。如果您正在用 node 编写项目,您应该能够将 scss-lint 作为 pre-commit 钩子使用,而无需向您的项目添加 Gemfile 或了解如何安装 scss-lint。

我们构建 pre-commit 来解决我们的钩子问题。它是一个用于 pre-commit 钩子的多语言包管理器。您指定您想要的钩子列表,pre-commit 会在每次提交之前管理任何用任何语言编写的钩子的安装和执行。pre-commit 专门设计为不需要 root 访问权限。如果您的开发人员之一没有安装 node 但修改了 JavaScript 文件,pre-commit 会自动处理下载和构建 node 以运行 eslint,而无需 root 权限。

在您运行钩子之前,您需要安装 pre-commit 包管理器。

使用 pip

pip install pre-commit

在 Python 项目中,将以下内容添加到您的 requirements.txt(或 requirements-dev.txt)中

pre-commit

作为 0 依赖项的 zipapp

  • github 发布 中找到并下载 .pyz 文件
  • 运行 python pre-commit-#.#.#.pyz ... 以代替 pre-commit ...

快速入门

1. 安装 pre-commit

  • 按照上面的 安装 指示操作
  • pre-commit --version 应该显示您正在使用的版本
$ pre-commit --version
pre-commit 4.0.1

2. 添加 pre-commit 配置

  • 创建一个名为 .pre-commit-config.yaml 的文件
  • 您可以使用 pre-commit sample-config 生成一个非常基本的配置
  • 配置的完整选项列表在 下面
  • 此示例使用 Python 代码的格式化程序,但是 pre-commit 可用于任何编程语言
  • 其他 支持的钩子 也可用
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. 安装 git 钩子脚本

  • 运行 pre-commit install 以设置 git 钩子脚本
$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
  • 现在 pre-commit 将在 git commit 上自动运行!

4.(可选)对所有文件运行

  • 在添加新的钩子时,通常最好对所有文件运行钩子(通常 pre-commit 仅在 git 钩子期间对已更改的文件运行)
$ 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
  • 糟糕!看起来我有一些尾随空格
  • 也考虑在 CI 中运行它

安装 pre-commit 后,可以通过 .pre-commit-config.yaml 配置文件将 pre-commit 插件添加到您的项目中。

在项目的根目录中添加一个名为 .pre-commit-config.yaml 的文件。pre-commit 配置文件描述了安装了哪些存储库和钩子。

.pre-commit-config.yaml - 顶层

repos

一个 存储库映射 列表。

default_install_hook_types

(可选:默认为 [pre-commit])一个 --hook-type 列表,在运行 pre-commit install 时默认使用。

default_language_version

(可选:默认为 {})从语言到应为该语言使用的默认 language_version 的映射。这只会覆盖未设置 language_version 的单个钩子。

例如,要为 language: python 钩子使用 python3.7

default_language_version:
    python: python3.7

default_stages

(可选:默认为(所有阶段))钩子的 stages 属性的配置范围默认值。这只会覆盖未设置 stages 的单个钩子。

例如

default_stages: [pre-commit, pre-push]

files

(可选:默认为 '')全局文件包含模式。

exclude

(可选:默认为 ^$)全局文件排除模式。

fail_fast

(可选:默认为 false)设置为 true 以使 pre-commit 在第一次失败后停止运行钩子。

minimum_pre_commit_version

(可选:默认为 '0')要求最低版本的 pre-commit。

一个示例顶层

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

.pre-commit-config.yaml - repos

存储库映射告诉 pre-commit 从哪里获取钩子的代码。

repo

要从中 git clone 的存储库 URL 或以下特殊哨兵值之一:localmeta

rev

要克隆到的修订版或标签。

hooks

一个 钩子映射 列表。

一个示例存储库

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

.pre-commit-config.yaml - hooks

钩子映射配置使用存储库中的哪个钩子,并允许自定义。所有可选键都将从存储库的配置中接收其默认值。

id

要使用的存储库中的哪个钩子。

alias

(可选)允许在使用 pre-commit run <hookid> 时使用其他 id 引用钩子。

name

(可选)覆盖钩子的名称 - 在钩子执行期间显示。

language_version

(可选)覆盖钩子的语言版本。请参阅 覆盖语言版本

files

(可选)覆盖要运行的文件的默认模式。

exclude

(可选)文件排除模式。

types

(可选)覆盖要运行的文件类型(AND)。请参阅 使用类型过滤文件

types_or

(可选)覆盖要运行的文件类型(OR)。请参阅 使用类型过滤文件

exclude_types

(可选)要排除的文件类型。

args

(可选)要传递给钩子的其他参数列表。

stages

(可选)选择要为其运行的 git 钩子。请参阅 将钩子限制在特定阶段运行

additional_dependencies

(可选)将在运行此钩子的环境中安装的依赖项列表。一个有用的应用程序是安装钩子的插件,例如 eslint

always_run

(可选)如果为 true,即使没有匹配的文件,此钩子也会运行。

verbose

(可选)如果为 true,即使钩子通过,也会强制打印钩子的输出。

log_file

(可选)如果存在,当钩子失败或 verbosetrue 时,钩子输出还会写入文件。

一个完整配置的示例

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

此配置表示下载 pre-commit-hooks 项目并运行其 trailing-whitespace 钩子。

自动更新钩子

您可以通过运行 pre-commit autoupdate 自动将钩子更新到最新版本。默认情况下,这会将钩子带到默认分支上的最新标签。

运行 pre-commit install 将 pre-commit 安装到您的 git 钩子中。pre-commit 现在将在每次提交时运行。每次使用 pre-commit 克隆项目时,运行 pre-commit install 始终应该是您要做的第一件事。

如果要手动对存储库运行所有 pre-commit 钩子,请运行 pre-commit run --all-files。要运行单个钩子,请使用 pre-commit run <hook_id>

pre-commit 第一次在文件上运行时,将自动下载、安装并运行钩子。请注意,第一次运行钩子可能会很慢。例如:如果机器没有安装 node,pre-commit 将下载并构建 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 目前支持用 多种语言 编写的钩子。只要您的 git 存储库是可安装的包(gem、npm、pypi 等)或公开了可执行文件,它就可以与 pre-commit 一起使用。每个 git 存储库可以根据您的需要支持任意多种语言/钩子。

钩子必须在失败或修改文件时退出非零值。

包含 pre-commit 插件的 git 存储库必须包含一个 .pre-commit-hooks.yaml 文件,该文件告诉 pre-commit

id

钩子的 id - 在 pre-commit-config.yaml 中使用。

name

钩子的名称 - 在钩子执行期间显示。

entry

入口点 - 要运行的可执行文件。entry 还可以包含不会被覆盖的参数,例如 entry: autopep8 -i

language

钩子的语言 - 告诉 pre-commit 如何安装钩子。

files

(可选:默认为 '')要运行的文件的模式。

exclude

(可选:默认为 ^$)排除由 files 匹配的文件。

types

(可选:默认为 [file])要运行的文件类型列表(AND)。请参阅 使用类型过滤文件

types_or

(可选:默认为 [])要运行的文件类型列表(OR)。请参阅 使用类型过滤文件

exclude_types

(可选:默认为 [])要排除的文件的模式。

always_run

(可选:默认为 false)如果为 true,即使没有匹配的文件,此钩子也会运行。

fail_fast

(可选:默认为 false)如果为 true,如果此钩子失败,pre-commit 将停止运行钩子。

verbose

(可选:默认为 false)如果为 true,即使钩子通过,也会强制打印钩子的输出。

pass_filenames

(可选:默认为 true)如果为 false,则不会将任何文件名传递给钩子。

require_serial

(可选:默认为 false)如果为 true,此钩子将使用单个进程而不是并行执行。

description

(可选:默认为 '')钩子的描述。仅用于元数据目的。

language_version

(可选: 默认值 default) 请参阅 覆盖语言版本

minimum_pre_commit_version

(可选: 默认值 '0') 允许指示 pre-commit 的最低兼容版本。

args

(可选: 默认值 []) 传递给钩子的额外参数列表。

stages

(可选: 默认值 (所有阶段)) 选择要运行的 Git 钩子。请参阅 限制钩子在特定阶段运行

例如

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

交互式开发钩子

由于 .pre-commit-config.yamlrepo 属性可以引用 git clone ... 理解的任何内容,因此在开发钩子时将其指向本地目录通常很有用。

pre-commit try-repo 通过启用一种快速尝试存储库的方法来简化此过程。以下是如何交互式工作的方法

注意:在将此命令与钩子类型 prepare-commit-msgcommit-msg 一起使用时,您可能需要提供 --commit-msg-filename

不需要提交才能在本地目录上 try-repopre-commit 将克隆任何已跟踪的未提交更改。

~/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!

支持的语言

conda

钩子存储库必须包含一个 environment.yml 文件,该文件将通过 conda env create --file environment.yml ... 来创建环境。

conda 语言也支持 additional_dependencies,并将任何值直接传递到 conda install 中。因此,此语言可与 本地 钩子一起使用。

可以通过 PRE_COMMIT_USE_MAMBA=1PRE_COMMIT_USE_MICROMAMBA=1 环境变量使用 mambamicromamba 进行安装。

支持:只要系统安装了 conda 二进制文件(例如 miniconda),conda 钩子就能正常工作。它已在 Linux、macOS 和 Windows 上进行了测试。

coursier

钩子存储库必须具有一个 .pre-commit-channel 文件夹,并且该文件夹必须包含 coursier 应用程序描述符,以便钩子安装。为了配置 coursier 钩子,您的 entry 应该对应于从存储库的 .pre-commit-channel 文件夹安装的可执行文件。

支持:已知 coursier 钩子可以在安装了 cscoursier 包管理器的任何系统上工作。您安装的特定 coursier 应用程序可能依赖于 JVM 的不同版本,请参阅钩子的文档以了解更多信息。它已在 Linux 上进行了测试。

pre-commit 也支持包管理器可执行文件的 coursier 命名。

3.0.0 中的新增功能language: coursier 钩子现在支持 repo: localadditional_dependencies

dart

钩子存储库必须具有一个 pubspec.yaml -- 它必须包含一个 executables 部分,该部分将列出安装后可用的二进制文件。将 entry 与可执行文件匹配。

pre-commit 将使用 dart compile exe bin/{executable}.dart 构建每个可执行文件。

language: dart 也支持 additional_dependencies。要为依赖项指定版本,请使用 : 分隔包名称。

        additional_dependencies: ['hello_world_dart:1.0.0']

支持:已知 dart 钩子可以在安装了 dart sdk 的任何系统上工作。它已在 Linux、macOS 和 Windows 上进行了测试。

docker

钩子存储库必须具有一个 Dockerfile。它将通过 docker build . 进行安装。

运行 Docker 钩子需要在主机上运行 Docker 引擎。为了配置 Docker 钩子,您的 entry 应该对应于 Docker 容器内的可执行文件,并将用于覆盖默认的容器入口点。当 pre-commit 将文件列表作为参数传递给运行容器命令时,您的 Docker CMD 不会运行。Docker 允许您使用任何 pre-commit 未作为内置功能支持的语言。

pre-commit 将自动挂载存储库源作为卷,使用 -v $PWD:/src:rw,Z 并使用 --workdir /src 设置工作目录。

支持:已知 docker 钩子可以在任何具有 docker 可执行文件的系统上工作。它已在 Linux 和 macOS 上进行了测试。通过 boot2docker 运行的钩子无法修改文件。

请参阅 此存储库 以获取基于 Docker 的钩子的示例。

docker_image

一种更轻量级的方法来使用 docker 钩子。docker_image “语言” 使用现有的 Docker 镜像来提供钩子可执行文件。

docker_image 钩子可以方便地配置为 本地 钩子。

entry 指定要使用的 Docker 标签。如果镜像定义了 ENTRYPOINT,则无需进行任何特殊操作即可连接可执行文件。如果容器未指定 ENTRYPOINT 或您想更改入口点,您也可以在 entry 中指定它。

例如

-   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 钩子使用 dotnet CLI 的系统安装进行安装。

钩子存储库必须包含一个 dotnet CLI 工具,可以根据 示例进行 packinstallentry 应该与构建存储库创建的可执行文件匹配。目前不支持其他依赖项。

支持:已知 dotnet 钩子可以在安装了 dotnet CLI 的任何系统上工作。它已在 Linux 和 Windows 上进行了测试。

fail

一种轻量级的 language,用于根据文件名禁止文件。fail 语言对于 本地 钩子特别有用。

钩子失败时将打印 entry。建议为 name 提供简短的描述,并在 entry 中提供更详细的修复说明。

以下是一个示例,它可以防止除以 .rst 结尾的文件之外的任何文件添加到 changelog 目录中

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

golang

钩子存储库必须包含 Go 源代码。它将通过 go install ./... 进行安装。pre-commit 将为每个钩子创建一个隔离的 GOPATH,并且 entry 应该与将安装到 GOPATHbin 目录中的可执行文件匹配。

此语言支持 additional_dependencies,并将任何值直接传递到 go install 中。它可以用作 repo: local 钩子。

2.17.0 中的更改:以前使用 go get ./...

3.0.0 中的新增功能:如果不存在 go,pre-commit 将引导 golanguage: golang 现在也支持 language_version

支持:已知 golang 钩子可以在安装了 Go 的任何系统上工作。它已在 Linux、macOS 和 Windows 上进行了测试。

haskell

3.4.0 中的新增功能

钩子存储库必须具有一个或多个 *.cabal 文件。安装后,这些包中的 executable 将可用于 entry

此语言支持 additional_dependencies,因此它可以用作 repo: local 钩子。

支持:已知 haskell 钩子可以在安装了 cabal 的任何系统上工作。它已在 Linux、macOS 和 Windows 上进行了测试。

lua

Lua 钩子使用 Luarocks 使用的 Lua 版本安装。

支持:已知 Lua 钩子可以在安装了 Luarocks 的任何系统上工作。它已在 Linux 和 macOS 上进行了测试,并且可能在 Windows 上也能工作。

node

钩子存储库必须具有一个 package.json。它将通过 npm install . 进行安装。已安装的包将提供一个可执行文件,该文件将与 entry 匹配 - 通常通过 package.json 中的 bin 进行匹配。

支持:node 钩子无需任何系统级依赖项即可工作。它已在 Linux、Windows 和 macOS 上进行了测试,并且可能在 Cygwin 下也能工作。

perl

Perl 钩子使用 cpan 的系统安装进行安装,cpan 是 Perl 附带的 CPAN 包安装程序。

钩子存储库必须包含 cpan 支持的内容,通常是 Makefile.PLBuild.PL,它用于将可执行文件安装到钩子的 entry 定义中。存储库将通过 cpan -T . 进行安装(已安装的文件存储在您的 pre-commit 缓存中,不会污染其他 Perl 安装)。

为 Perl 指定 additional_dependencies 时,您可以使用 cpan 理解的任何 安装参数格式

支持:Perl 钩子目前需要预先存在的 Perl 安装,包括 PATH 中的 cpan 工具。它已在 Linux、macOS 和 Windows 上进行了测试。

python

钩子存储库必须可以通过 pip install . 进行安装(通常通过 setup.pypyproject.toml)。已安装的包将提供一个可执行文件,该文件将与 entry 匹配 - 通常通过 setup.py 中的 console_scriptsscripts 进行匹配。

此语言也支持 additional_dependencies,因此它可以与 本地 钩子一起使用。指定的依赖项将附加到 pip install 命令中。

支持:python 钩子无需任何系统级依赖项即可工作。它已在 Linux、macOS、Windows 和 Cygwin 上进行了测试。

r

此钩子存储库必须具有一个 renv.lock 文件,该文件将在钩子安装时使用 renv::restore() 恢复。如果存储库是 R 包(即在 DESCRIPTION 中具有 Type: Package),则会安装它。在 entry 中支持的语法是 Rscript -e {expression}Rscript path/relative/to/hook/root。R 启动过程将被跳过(模拟 --vanilla),因为所有配置都应通过 args 公开,以实现最大的透明度和可移植性。

为 R 指定 additional_dependencies 时,您可以使用 renv::install() 理解的任何安装参数格式。

支持:只要安装了 R 并且在 PATH 中,r 钩子就能正常工作。它已在 Linux、macOS 和 Windows 上进行了测试。

ruby

钩子仓库必须包含一个*.gemspec文件。它将通过gem build *.gemspec && gem install *.gem进行安装。安装的包将生成一个可执行文件,该可执行文件将与entry匹配 – 通常通过gemspec中的executables来实现。

支持:ruby钩子无需任何系统级依赖项即可工作。它已在linux和macOS上进行了测试,并且可能在cygwin下工作。

rust

Rust钩子使用Cargo(Rust的官方包管理器)进行安装。

钩子仓库必须包含一个Cargo.toml文件,该文件至少生成一个二进制文件(示例),其名称应与钩子的entry定义匹配。仓库将通过cargo install --bins进行安装(二进制文件存储在您的pre-commit缓存中,不会污染您的用户级Cargo安装)。

为Rust指定additional_dependencies时,可以使用语法{package_name}:{package_version}来指定新的库依赖项(用于构建您的钩子仓库),或使用特殊语法cli:{package_name}:{package_version}来指定CLI依赖项(单独构建,并将二进制文件提供给钩子使用)。

pre-commit将引导rust(如果不存在)。language: rust还支持language_version

支持:它已在linux、Windows和macOS上进行了测试。

swift

钩子仓库必须包含一个Package.swift文件。它将通过swift build -c release进行安装。entry应与构建仓库创建的可执行文件匹配。

支持:swift钩子已知可在安装了swift的任何系统上工作。它已在linux和macOS上进行了测试。

pygrep

grep的跨平台python实现 – pygrep钩子是一种快速编写简单钩子的方法,它通过文件匹配来阻止提交。将正则表达式指定为entryentry可以是任何python正则表达式。对于不区分大小写的正则表达式,您可以将(?i)标志作为条目开头应用,或使用args: [-i]

对于多行匹配,请使用args: [--multiline]

要要求所有文件都匹配,请使用args: [--negate]

支持:pygrep钩子在pre-commit运行的所有平台上都受支持。

script

脚本钩子提供了一种编写简单脚本以验证文件的方法。entry应为相对于钩子仓库根目录的路径。

此钩子类型不会获得虚拟环境来使用 – 如果它需要其他依赖项,则使用者必须手动安装它们。

支持:脚本钩子的支持取决于脚本本身。

system

系统钩子提供了一种为系统级可执行文件编写钩子的方法,这些可执行文件没有上面支持的语言(或具有特殊的环境要求,不允许它们在隔离状态下运行,例如pylint)。

此钩子类型不会获得虚拟环境来使用 – 如果它需要其他依赖项,则使用者必须手动安装它们。

支持:系统钩子的支持取决于可执行文件。

所有pre-commit命令都接受以下选项

  • --color {auto,always,never}:是否在输出中使用颜色。默认为auto。可以通过使用PRE_COMMIT_COLOR={auto,always,never}覆盖,或使用TERM=dumb禁用。
  • -c CONFIG, --config CONFIG:替代配置文件的路径
  • -h, --help:显示帮助和可用选项。

pre-commit以特定的代码退出

  • 1:检测到的/预期的错误
  • 3:意外错误
  • 130:进程被^C中断

pre-commit autoupdate [options]

自动更新pre-commit配置到最新仓库版本。

选项

  • --bleeding-edge:更新到默认分支的最新版本,而不是最新的标记版本(默认行为)。
  • --freeze:在rev中存储“冻结”的哈希值,而不是标签名称。
  • --repo REPO:仅更新此仓库。此选项可以多次指定。
  • -j / --jobs3.3.0新增 要使用的线程数(默认值:1)。

以下是一些使用此.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将优先选择包含.的标签。

pre-commit clean [options]

清理缓存的pre-commit文件。

选项:(无其他选项)

pre-commit gc [options]

清理未使用的缓存仓库。

pre-commit保留已安装钩子仓库的缓存,该缓存会随着时间的推移而增长。此命令可以定期运行以清理缓存目录中未使用的仓库。

选项:(无其他选项)

pre-commit init-templatedir DIRECTORY [options]

在打算与git config init.templateDir一起使用的目录中安装钩子脚本。

选项

  • -t HOOK_TYPE, --hook-type HOOK_TYPE:要安装的钩子类型。

一些有用的示例调用

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

对于Windows cmd.exe,请使用%HOMEPATH%代替~

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

对于Windows PowerShell,请使用$HOME代替~

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

现在,每当克隆或创建仓库时,它都将已设置好钩子!

pre-commit install [options]

安装pre-commit脚本。

选项

  • -f, --overwrite:用pre-commit脚本替换任何现有的git钩子。
  • --install-hooks:现在还安装所有可用钩子的环境(而不是在第一次执行时)。请参阅pre-commit install-hooks
  • -t HOOK_TYPE, --hook-type HOOK_TYPE:指定要安装的钩子类型。
  • --allow-missing-config:钩子脚本将允许缺少配置文件。

一些有用的示例调用

  • pre-commit install:默认调用。将钩子脚本安装在任何现有的git钩子旁边。
  • pre-commit install --install-hooks --overwrite:幂等地用pre-commit替换现有的git钩子脚本,并安装钩子环境。

如果命令行上未指定--hook-type,则pre-commit install将从default_install_hook_types安装钩子。

pre-commit install-hooks [options]

安装所有可用钩子缺少的环境。除非执行此命令或install --install-hooks,否则每个钩子的环境将在第一次调用钩子时创建。

每个钩子都在适合钩子编写语言的单独环境中初始化。请参阅支持的语言

此命令不会安装pre-commit脚本。要在一条命令中安装脚本以及钩子环境,请使用pre-commit install --install-hooks

选项:(无其他选项)

pre-commit migrate-config [options]

将列表配置迁移到新的映射配置格式。

选项:(无其他选项)

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

运行钩子。

选项

  • [hook-id]:指定单个钩子ID,仅运行该钩子。
  • -a, --all-files:在仓库中的所有文件上运行。
  • --files [FILES [FILES ...]]:要运行钩子的特定文件名。
  • --from-ref FROM_REF + --to-ref TO_REF:针对git中FROM_REF...TO_REF之间更改的文件运行。
  • --hook-stage STAGE:选择要运行的阶段
  • --show-diff-on-failure:当钩子失败时,直接在其后运行git diff
  • -v, --verbose:生成与成功无关的钩子输出。在输出中包含钩子ID。

一些有用的示例调用

  • pre-commit run:这是pre-commit在提交时默认运行的内容。这将针对当前暂存的文件运行所有钩子。
  • pre-commit run --all-files:针对所有文件运行所有钩子。如果您在CI中使用pre-commit,这是一个有用的调用。
  • pre-commit run flake8:针对所有暂存的文件运行flake8钩子。
  • git ls-files -- '*.py' | xargs pre-commit run --files:针对仓库中所有*.py文件运行所有钩子。
  • pre-commit run --from-ref HEAD^^^ --to-ref HEAD:针对HEAD^^^HEAD之间更改的文件运行。此形式在预接收钩子中使用时非常有用。

pre-commit sample-config [options]

生成一个示例.pre-commit-config.yaml

选项:(无其他选项)

pre-commit try-repo REPO [options]

尝试仓库中的钩子,这对于开发新钩子很有用。try-repo也可用于在将仓库添加到配置之前对其进行测试。try-repo在运行钩子之前打印它根据远程钩子仓库生成的配置。

选项

  • REPO:必需的可克隆钩子仓库。可以是磁盘上的本地路径。
  • --ref REF:手动选择要运行的引用,否则将使用HEAD修订版。
  • pre-commit try-repo还支持pre-commit run的所有可用选项。

一些有用的示例调用

  • pre-commit try-repo https://github.com/pre-commit/pre-commit-hooks:运行pre-commit/pre-commit-hooks最新修订版中的所有钩子。
  • pre-commit try-repo ../path/to/repo:运行磁盘上仓库中的所有钩子。
  • pre-commit try-repo ../pre-commit-hooks flake8:仅运行本地../pre-commit-hooks仓库中配置的flake8钩子。
  • 请参阅pre-commit run,了解run的其他有用调用,这些调用也受pre-commit try-repo支持。

pre-commit uninstall [options]

卸载pre-commit脚本。

选项

  • -t HOOK_TYPE, --hook-type HOOK_TYPE:要卸载的钩子类型。

以迁移模式运行

默认情况下,如果您有现有的钩子,pre-commit install将以迁移模式安装,该模式将运行您现有的钩子和pre-commit的钩子。要禁用此行为,请向install命令传递-f / --overwrite。如果您决定不使用pre-commit,pre-commit uninstall将恢复安装之前的钩子状态。

临时禁用钩子

并非所有钩子都完美无缺,因此有时您可能需要跳过一个或多个钩子的执行。pre-commit通过查询SKIP环境变量来解决此问题。SKIP环境变量是一个用逗号分隔的钩子ID列表。这允许您跳过单个钩子,而不是对整个提交使用--no-verify

$ SKIP=flake8 git commit -m "foo"

将钩子限制在特定阶段运行

pre-commit支持许多不同类型的git钩子(不仅仅是pre-commit!)。

钩子提供者可以通过在 .pre-commit-hooks.yaml 中设置 stages 属性来选择他们在哪些 Git 钩子上运行,也可以通过在 .pre-commit-config.yaml 中设置 stages 来覆盖它。如果在这两个地方都没有设置 stages,则默认值将从顶级 default_stages 选项中获取(默认为所有阶段)。默认情况下,工具会为 pre-commit 支持的 每种钩子类型 启用。

3.2.0 中新增stages 的值与钩子名称匹配。以前,commitpushmerge-commit 分别匹配 pre-commitpre-pushpre-merge-commit

manual 阶段(通过 stages: [manual])是一个特殊的阶段,不会被任何 git 钩子自动触发——如果您想添加一个不会自动运行但可以通过 pre-commit run --hook-stage manual [hookid] 按需运行的工具,这将非常有用。

如果您正在编写工具,通常最好提供一个合适的 stages 属性。例如,对于 lint 工具或代码格式化工具,合理的设置是 stages: [pre-commit, pre-merge-commit, pre-push, manual]

要为特定的 Git 钩子安装 pre-commit,请将 --hook-type 传递给 pre-commit install。可以多次指定此选项,例如

$ pre-commit install --hook-type pre-commit --hook-type pre-push
pre-commit installed at .git/hooks/pre-commit
pre-commit installed at .git/hooks/pre-push

此外,可以通过设置顶级 default_install_hook_types 来指定一组默认的 Git 钩子类型进行安装。

例如

default_install_hook_types: [pre-commit, pre-push, commit-msg]
$ pre-commit  install
pre-commit installed at .git/hooks/pre-commit
pre-commit installed at .git/hooks/pre-push
pre-commit installed at .git/hooks/commit-msg

支持的 Git 钩子

commit-msg

git commit-msg 文档

commit-msg 钩子将传递一个文件名——此文件包含要验证的提交消息的当前内容。如果存在非零退出代码,则提交将被中止。

post-checkout

git post-checkout 文档

post-checkout 钩子在 checkout 发生之后运行,可用于设置或管理存储库中的状态。

post-checkout 钩子不操作文件,因此必须将其设置为 always_run: true,否则它们将始终被跳过。

环境变量

  • PRE_COMMIT_FROM_REFpost-checkout Git 钩子的第一个参数
  • PRE_COMMIT_TO_REFpost-checkout Git 钩子的第二个参数
  • PRE_COMMIT_CHECKOUT_TYPEpost-checkout Git 钩子的第三个参数

post-commit

git post-commit 文档

post-commit 在提交已成功完成之后运行,因此不能用于阻止提交发生。

post-commit 钩子不操作文件,因此必须将其设置为 always_run: true,否则它们将始终被跳过。

post-merge

git post-merge 文档

post-merge 在成功的 git merge 之后运行。

post-merge 钩子不操作文件,因此必须将其设置为 always_run: true,否则它们将始终被跳过。

环境变量

  • PRE_COMMIT_IS_SQUASH_MERGEpost-merge Git 钩子的第一个参数。

post-rewrite

git post-rewrite 文档

post-rewrite 在修改历史记录的 Git 命令(例如 git commit --amendgit rebase)之后运行。

post-rewrite 钩子不操作文件,因此必须将其设置为 always_run: true,否则它们将始终被跳过。

环境变量

  • PRE_COMMIT_REWRITE_COMMANDpost-rewrite Git 钩子的第一个参数。

pre-commit

git pre-commit 文档

pre-commit 在提交完成之前触发,以允许检查正在提交的代码。在未暂存的更改上运行钩子可能会导致提交期间出现误报和漏报。pre-commit 仅在文件的暂存内容上运行,方法是在运行钩子时临时存储未暂存的更改。

pre-merge-commit

git pre-merge-commit 文档

pre-merge-commit 在合并成功但创建合并提交之前触发。此钩子在合并的所有暂存文件上运行。

请注意,您需要使用至少 Git 2.24 版本才能使用此钩子。

pre-push

git pre-push 文档

pre-pushgit push 时触发。

环境变量

  • PRE_COMMIT_FROM_REF:正在推送到哪个修订版。
  • PRE_COMMIT_TO_REF:正在推送到远程的本地修订版。
  • PRE_COMMIT_REMOTE_NAME:正在推送到哪个远程(例如 origin)。
  • PRE_COMMIT_REMOTE_URL:正在推送到哪个远程的 URL(例如 [email protected]:pre-commit/pre-commit)。
  • PRE_COMMIT_REMOTE_BRANCH:正在推送到哪个远程分支的名称(例如 refs/heads/target-branch)。
  • PRE_COMMIT_LOCAL_BRANCH:正在推送到远程的本地分支的名称(例如 HEAD)。

pre-rebase

3.2.0 中新增

git pre-rebase 文档

pre-rebase 在变基发生之前触发。钩子失败可能会取消变基操作。

pre-rebase 钩子不操作文件,因此必须将其设置为 always_run: true,否则它们将始终被跳过。

环境变量

  • PRE_COMMIT_PRE_REBASE_UPSTREAMpre-rebase Git 钩子的第一个参数
  • PRE_COMMIT_PRE_REBASE_BRANCHpre-rebase Git 钩子的第二个参数。

prepare-commit-msg

git prepare-commit-msg 文档

prepare-commit-msg 钩子将传递一个文件名——此文件可能为空,也可能包含来自 -m 或其他模板的提交消息。prepare-commit-msg 钩子可以修改此文件的内容以更改将要提交的内容。钩子可能需要检查 GIT_EDITOR=:,因为这表示不会启动任何编辑器。如果钩子以非零退出,则提交将被中止。

环境变量

  • PRE_COMMIT_COMMIT_MSG_SOURCEprepare-commit-msg Git 钩子的第二个参数
  • PRE_COMMIT_COMMIT_OBJECT_NAMEprepare-commit-msg Git 钩子的第三个参数

向钩子传递参数

有时钩子需要参数才能正确运行。您可以通过在 .pre-commit-config.yaml 中指定 args 属性来传递静态参数,如下所示

-   repo: https://github.com/PyCQA/flake8
    rev: 4.0.1
    hooks:
    -   id: flake8
        args: [--max-line-length=131]

这将向 flake8 传递 --max-line-length=131

钩子中的参数模式

如果您正在编写自己的自定义钩子,则您的钩子应该期望接收 args 值,然后是暂存文件列表。

例如,假设一个 .pre-commit-config.yaml

-   repo: https://github.com/path/to/your/hook/repo
    rev: badf00ddeadbeef
    hooks:
    -   id: my-hook-script-id
        args: [--myarg1=1, --myarg1=2]

下次运行 pre-commit 时,您的脚本将被调用

path/to/script-or-system-exe --myarg1=1 --myarg1=2 dir/file1 dir/file2 file3

如果 args 属性为空或未定义,则您的脚本将被调用

path/to/script-or-system-exe dir/file1 dir/file2 file3

创建本地钩子时,没有理由将命令参数放入 args 中,因为没有任何内容可以覆盖它们——而是将您的参数直接放在钩子 entry 中。

例如

-   repo: local
    hooks:
    -   id: check-requirements
        name: check requirements files
        language: system
        entry: python -m scripts.check_requirements --compare
        files: ^requirements.*\.txt$

存储库本地钩子

存储库本地钩子在以下情况下很有用:

  • 脚本与存储库紧密耦合,并且将钩子脚本与存储库一起分发是有意义的。
  • 钩子需要存储库构建工件中才有的状态(例如,您的应用程序的 virtualenv 用于 pylint)。
  • lint 工具的官方存储库没有 pre-commit 元数据。

您可以通过将 repo 指定为哨兵 local 来配置存储库本地钩子。

本地钩子可以使用任何支持 additional_dependenciesdocker_image / fail / pygrep / script / system 的语言。这使您可以安装以前需要微不足道的镜像存储库才能安装的东西。

local 钩子必须定义 idnamelanguageentryfiles / types,如 创建新的钩子 中所述。

这是一个包含一些 local 钩子的示例配置

-   repo: local
    hooks:
    -   id: pylint
        name: pylint
        entry: pylint
        language: system
        types: [python]
        require_serial: true
    -   id: check-x
        name: Check X
        entry: ./bin/check-x.sh
        language: script
        files: \.x$
    -   id: scss-lint
        name: scss-lint
        entry: scss-lint
        language: ruby
        language_version: 2.1.5
        types: [scss]
        additional_dependencies: ['scss_lint:0.52.0']

元钩子

pre-commit 提供了一些用于检查 pre-commit 配置本身的有用钩子。可以使用 repo: meta 启用这些钩子。

-   repo: meta
    hooks:
    -   id: ...

当前可用的 meta 钩子

check-hooks-apply

确保配置的钩子至少适用于存储库中的一个文件。

check-useless-excludes

确保 exclude 指令适用于存储库中的任何文件。

identity

一个简单的钩子,打印传递给它的所有参数,用于调试。

在存储库中自动启用 pre-commit

pre-commit init-templatedir 可用于为 gitinit.templateDir 选项设置一个框架。这意味着任何新克隆的存储库都将自动设置钩子,而无需运行 pre-commit install

要进行配置,首先设置 gitinit.templateDir——在此示例中,我使用 ~/.git-template 作为我的模板目录。

$ git config --global init.templateDir ~/.git-template
$ pre-commit init-templatedir ~/.git-template
pre-commit installed at /home/asottile/.git-template/hooks/pre-commit

现在,无论何时克隆启用 pre-commit 的存储库,钩子都将已设置!

$ git clone -q [email protected]:asottile/pyupgrade
$ cd pyupgrade
$ git commit --allow-empty -m 'Hello world!'
Check docstring is first.............................(no files to check)Skipped
Check Yaml...........................................(no files to check)Skipped
Debug Statements (Python)............................(no files to check)Skipped
...

init-templatedir 使用 pre-commit install 中的 --allow-missing-config 选项,因此没有配置文件的存储库将被跳过

$ git init sample
Initialized empty Git repository in /tmp/sample/.git/
$ cd sample
$ git commit --allow-empty -m 'Initial commit'
`.pre-commit-config.yaml` config file not found. Skipping `pre-commit`.
[main (root-commit) d1b39c1] Initial commit

要仍然需要选择加入,但提示用户设置 pre-commit,请使用以下模板钩子(例如在 ~/.git-template/hooks/pre-commit 中)。

#!/usr/bin/env bash
if [ -f .pre-commit-config.yaml ]; then
    echo 'pre-commit configuration detected, but `pre-commit install` was never run' 1>&2
    exit 1
fi

这样,忘记的 pre-commit install 就会在提交时产生错误

$ git clone -q https://github.com/asottile/pyupgrade
$ cd pyupgrade/
$ git commit -m 'foo'
pre-commit configuration detected, but `pre-commit install` was never run

使用类型过滤文件

使用 types 进行过滤比使用 files 进行传统过滤具有几个优势。

  • 没有容易出错的正则表达式
  • 可以通过其 shebang 匹配文件(即使没有扩展名)
  • 可以轻松忽略符号链接/子模块

types 作为标签数组在每个钩子中指定。这些标签通过 identify 库的一组启发式方法发现。选择 identify 是因为它是一个小型便携式纯 Python 库。

您在 identify 中会发现的一些常用标签

要发现磁盘上任何文件的类型,您可以使用 identify 的命令行界面

$ identify-cli setup.py
["file", "non-executable", "python", "text"]
$ identify-cli some-random-file
["file", "non-executable", "text"]
$ identify-cli --filename-only some-random-file; echo $?
1

如果您使用的文件扩展名不受支持,请 提交一个拉取请求

typestypes_orfiles 在过滤时会与 AND 一起评估。types 中的标签也会使用 AND 进行评估。

types_or 中的标签使用 OR 进行评估。

例如

    files: ^foo/
    types: [file, python]

将匹配文件 foo/1.py,但不会匹配 setup.py

另一个例子

    files: ^foo/
    types_or: [javascript, jsx, ts, tsx]

将匹配 foo/bar.js / foo/bar.jsx / foo/bar.ts / foo/bar.tsx 中的任何一个,但不会匹配 baz.js

如果您想在使用现有钩子时匹配一个未包含在 type 中的文件路径,则需要回退到仅通过覆盖 types 设置来匹配 files。以下是如何使用 check-json 针对非 JSON 文件的示例

    -   id: check-json
        types: [file]  # override `types: [json]`
        files: \.(json|myext)$

文件也可以通过 Shebang 进行匹配。使用 types: python 时,以 #!/usr/bin/env python3 开头的 exe 文件也将被匹配。

filesexclude 一样,您也可以在必要时使用 exclude_types 排除类型。

正则表达式

filesexclude 的模式是 Python 正则表达式,并使用 re.search 进行匹配。

因此,您可以使用 Python 正则表达式支持的任何功能。

如果您发现由于排除/包含事项的列表过长而导致正则表达式变得难以处理,您可能会发现 详细 正则表达式很有用。可以使用 YAML 的多行文字和 (?x) 正则表达式标记来启用此功能。

# ...
    -   id: my-hook
        exclude: |
            (?x)^(
                path/to/file1.py|
                path/to/file2.py|
                path/to/file3.py
            )$

覆盖语言版本

有时您只想在特定版本的语言上运行钩子。对于每种语言,它们默认使用系统安装的语言(例如,如果我正在运行 python3.7 并且一个钩子指定了 python,则 pre-commit 将使用 python3.7 运行该钩子)。有时您不希望使用默认的系统安装版本,因此您可以通过设置 language_version 在每个钩子的基础上覆盖它。

-   repo: https://github.com/pre-commit/mirrors-scss-lint
    rev: v0.54.0
    hooks:
    -   id: scss-lint
        language_version: 2.1.5

这告诉 pre-commit 使用 Ruby 2.1.5 来运行 scss-lint 钩子。

特定语言的有效值列在下面

  • python:您拥有的任何系统安装的 Python 解释器。此参数的值将作为 -p 传递给 virtualenv
    • 在 Windows 上,pep394 名称将被转换为 Py 启动器调用以实现可移植性。因此,即使在 Windows 上,也继续使用诸如 python3py -3)或 python3.6py -3.6)之类的名称。
  • node:请参阅 nodeenv
  • ruby:请参阅 ruby-build
  • rust:language_version 将传递给 rustup
  • 3.0.0 中的新增功能 golang:使用 go.dev/dl 上的版本,例如 1.19.5

您可以在配置的 顶层 设置 default_language_version 以控制所有语言钩子的默认版本。

default_language_version:
    # force all unspecified python hooks to run python3
    python: python3
    # force all unspecified ruby hooks to run ruby 2.1.5
    ruby: 2.1.5

为您的仓库添加徽章

您可以向您的仓库添加一个徽章,以向您的贡献者/用户表明您使用了 pre-commit!

pre-commit

  • Markdown

    [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
    
  • HTML

    <a href="https://github.com/pre-commit/pre-commit"><img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit" alt="pre-commit" style="max-width:100%;"></a>
    
  • reStructuredText

    .. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit
       :target: https://github.com/pre-commit/pre-commit
       :alt: pre-commit
    
  • AsciiDoc

    image:https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit[pre-commit, link=https://github.com/pre-commit/pre-commit]
    

在持续集成中使用

pre-commit 也可以用作持续集成的工具。例如,将 pre-commit run --all-files 作为 CI 步骤添加将确保所有内容都保持最佳状态。要仅检查已更改的文件,这可能会更快,请使用类似 pre-commit run --from-ref origin/HEAD --to-ref HEAD 的命令。

管理 CI 缓存

pre-commit 默认将其仓库存储在 ~/.cache/pre-commit 中 - 这可以通过两种方式配置

  • PRE_COMMIT_HOME:如果设置,pre-commit 将改用该位置。
  • XDG_CACHE_HOME:如果设置,pre-commit 将使用 $XDG_CACHE_HOME/pre-commit,遵循 XDG 基本目录规范

pre-commit.ci 示例

pre-commit.ci 中运行不需要任何额外的配置!

pre-commit.ci 还具有以下优势

  • 它比其他免费 CI 解决方案更快
  • 它将自动修复拉取请求
  • 它将定期自动更新您的配置

pre-commit.ci speed comparison

Appveyor 示例

cache:
- '%USERPROFILE%\.cache\pre-commit'

Azure Pipelines 示例

注意:Azure Pipelines 使用不可变缓存,因此 Python 版本和 .pre-commit-config.yaml 哈希必须包含在缓存密钥中。有关仓库模板,请参阅 [email protected]

jobs:
- job: precommit

  # ...

  variables:
    PRE_COMMIT_HOME: $(Pipeline.Workspace)/pre-commit-cache

  steps:

  # ...

  - script: echo "##vso[task.setvariable variable=PY]$(python -VV)"
  - task: CacheBeta@0
    inputs:
      key: pre-commit | .pre-commit-config.yaml | "$(PY)"
      path: $(PRE_COMMIT_HOME)

CircleCI 示例

Azure Pipelines 一样,CircleCI 也使用不可变缓存

  steps:
  - run:
    command: |
      cp .pre-commit-config.yaml pre-commit-cache-key.txt
      python --version --version >> pre-commit-cache-key.txt
  - restore_cache:
    keys:
    - v1-pc-cache-{{ checksum "pre-commit-cache-key.txt" }}

  # ...

  - save_cache:
    key: v1-pc-cache-{{ checksum "pre-commit-cache-key.txt" }}
    paths:
      - ~/.cache/pre-commit

(来源:@chriselion

GitHub Actions 示例

请参阅 官方 pre-commit GitHub Action

Azure Pipelines 一样,GitHub Actions 也使用不可变缓存

    - name: set PY
      run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
    - uses: actions/cache@v3
      with:
        path: ~/.cache/pre-commit
        key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}

GitLab CI 示例

请参阅 GitLab 缓存最佳实践 以微调缓存范围。

my_job:
  variables:
    PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
  cache:
    paths:
      - ${PRE_COMMIT_HOME}

pre-commit 的缓存需要在不同的构建之间从一个固定位置提供服务。当在 GitLab 上使用 K8s 运行程序时,这不是默认设置。如果您遇到 InvalidManifestError 错误,请将 builds_dir 设置为静态值,例如在您的 [[runner]] 配置中设置 builds_dir = "/builds"

Travis CI 示例

cache:
  directories:
  - $HOME/.cache/pre-commit

与 Tox 一起使用

Tox 用于配置测试/CI 工具,例如 pre-commit。tox>=2 的一个功能是它将清除环境变量,以便测试更具可重复性。在某些情况下,pre-commit 需要一些环境变量,因此必须允许它们传递。

当通过 SSH 克隆仓库(repo: [email protected]:...)时,git 需要 SSH_AUTH_SOCK 变量,否则将失败

[INFO] Initializing environment for [email protected]:pre-commit/pre-commit-hooks.
An unexpected error has occurred: CalledProcessError: command: ('/usr/bin/git', 'fetch', 'origin', '--tags')
return code: 128
expected return code: 0
stdout: (none)
stderr:
    [email protected]: Permission denied (publickey).
    fatal: Could not read from remote repository.

    Please make sure you have the correct access rights
    and the repository exists.

Check the log at /home/asottile/.cache/pre-commit/pre-commit.log

将以下内容添加到您的 Tox 测试环境中

[testenv]
passenv = SSH_AUTH_SOCK

同样,当通过 HTTP/HTTPS 克隆仓库(repo: https://github.com:...)时,您可能正在公司 HTTP(S) 代理服务器后面工作,在这种情况下,git 需要设置 http_proxyhttps_proxyno_proxy 变量,否则克隆可能会失败

[testenv]
passenv = http_proxy https_proxy no_proxy

使用仓库的最新版本

pre-commit 配置旨在提供可重复且快速的体验,因此有意不提供“未固定最新版本”的钩子仓库工具。

相反,pre-commit 提供了使用 pre-commit autoupdate 轻松升级到最新版本的工具。如果您需要钩子的绝对最新版本(而不是最新的标记版本),请将 --bleeding-edge 参数传递给 autoupdate

pre-commit 假设 rev 的值是不可变的引用(例如标签或 SHA),并将基于此进行缓存。不支持使用分支名称(或 HEAD)作为 rev 的值,它仅表示在安装钩子时该可变引用的状态(并且 *不会* 自动更新)。

我们希望发展这个项目并获得更多贡献者,特别是为了支持更多语言/版本。我们还希望将 .pre-commit-hooks.yaml 文件添加到流行的 lint 工具中,而无需维护 fork/镜像。

随时提交错误报告、拉取请求和功能请求。

赞助

如果您或您的公司希望支持 pre-commit 的开发,您可以通过以下方式做出贡献

获取帮助

有几种方法可以获得 pre-commit 的帮助

贡献者