pre-commit

一個用於管理和維護多語言 pre-commit 鉤子的框架。

加星標
pre-commit logo

Git 鉤子腳本可用於在提交程式碼審查之前識別簡單的問題。我們在每次提交時都會運行鉤子,以自動指出程式碼中的問題,例如缺少分號、尾隨空格和除錯語句。通過在程式碼審查之前指出這些問題,程式碼審查者可以專注於變更的架構,而不會浪費時間在瑣碎的風格挑剔上。

隨著我們建立越來越多的程式庫和專案,我們意識到在專案之間共用我們的 pre-commit 鉤子很麻煩。我們將笨重的 bash 腳本從一個專案複製貼上到另一個專案,並且必須手動更改鉤子以適應不同的專案結構。

我們相信您應該始終使用最好的行業標準程式碼檢查工具。一些最好的程式碼檢查工具是用您在專案中未使用或未安裝在機器上的語言編寫的。例如,scss-lint 是一個用 Ruby 編寫的 SCSS 程式碼檢查工具。如果您正在使用 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 ... 能理解的東西,因此在開發 hooks 時,將其指向本地目錄通常很有用。

pre-commit try-repo 簡化了這個過程,它提供了一種快速試用儲存庫的方法。以下是如何互動式操作的範例

注意:在將此命令與 hook 類型 prepare-commit-msgcommit-msg 一起使用時,您可能需要提供 --commit-msg-filename

在本地目錄上執行 try-repo 不需要提交。pre-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

hook 儲存庫必須包含一個 environment.yml 檔案,該檔案將通過 conda env create --file environment.yml ... 來建立環境。

conda 語言也支援 additional_dependencies,並且會將任何值直接傳遞給 conda install。因此,這種語言可以與 本地 hooks 一起使用。

可以通過 PRE_COMMIT_USE_MAMBA=1PRE_COMMIT_USE_MICROMAMBA=1 環境變數使用 mambamicromamba 進行安裝。

支援:只要系統安裝了 conda 二進制檔案(例如 miniconda),conda hooks 就能正常工作。它已經在 Linux、macOS 和 Windows 上進行過測試。

coursier

hook 儲存庫必須有一個 .pre-commit-channel 資料夾,並且該資料夾必須包含要安裝的 hook 的 coursier 應用程式描述符。若要設定 coursier hooks,您的 entry 應對應於從儲存庫的 .pre-commit-channel 資料夾安裝的可執行檔。

支援:已知 coursier hooks 可以在任何安裝了 cscoursier 套件管理器的系統上運作。您安裝的特定 coursier 應用程式可能取決於 JVM 的各種版本,請查閱 hooks 的文件以獲取說明。它已在 Linux 上進行過測試。

pre-commit 也支援套件管理器可執行檔的 coursier 命名。

3.0.0 版新增功能language: coursier hooks 現在支援 repo: localadditional_dependencies

dart

hook 儲存庫必須有一個 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 hooks 可以在任何安裝了 dart sdk 的系統上運作。它已在 Linux、macOS 和 Windows 上進行過測試。

docker

hook 儲存庫必須有一個 Dockerfile。它將通過 docker build . 安裝。

執行 Docker hooks 需要在您的主機上執行 Docker 引擎。若要設定 Docker hooks,您的 entry 應對應於 Docker 容器內的可執行檔,並且將用於覆蓋預設的容器進入點。當 pre-commit 將檔案列表作為參數傳遞給執行容器命令時,您的 Docker CMD 將不會執行。Docker 允許您使用 pre-commit 不支援的任何語言作為內建語言。

pre-commit 將使用 -v $PWD:/src:rw,Z 自動將儲存庫來源掛載為磁碟區,並使用 --workdir /src 設定工作目錄。

支援:已知 docker hooks 可以在任何具有有效的 docker 可執行檔的系統上運作。它已在 Linux 和 macOS 上進行過測試。已知通過 boot2docker 執行的 hooks 無法修改檔案。

有關基於 Docker 的 hook 範例,請參閱 此儲存庫

docker_image

一種更輕量級的 docker hooks 方法。docker_image「語言」使用現有的 docker 映像來提供 hook 可執行檔。

docker_image hooks 可以方便地設定為 本地 hooks。

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 hooks 使用 dotnet CLI 的系統安裝進行安裝。

Hook 儲存庫必須包含一個 dotnet CLI 工具,該工具可以根據 範例進行 packinstallentry 應與通過構建儲存庫建立的可執行檔匹配。目前不支援其他依賴項。

支援:已知 dotnet hooks 可以在任何安裝了 dotnet CLI 的系統上運作。它已在 Linux 和 Windows 上進行過測試。

fail

一種輕量級的 language,用於根據檔案名稱禁止檔案。fail 語言對於 本地 hooks 特別有用。

當 hook 失敗時,將會列印 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

hook 儲存庫必須包含 go 原始程式碼。它將通過 go install ./... 安裝。pre-commit 將為每個 hook 建立一個獨立的 GOPATH,並且 entry 應與將安裝到 GOPATHbin 目錄中的可執行檔匹配。

這種語言支援 additional_dependencies,並且會將任何值直接傳遞給 go install。它可以用作 repo: local hook。

2.17.0 版中的變更:先前使用的是 go get ./...

3.0.0 版新增功能:如果不存在 go,pre-commit 將會啟動它。language: golang 現在也支援 language_version

支援:已知 golang hooks 可以在任何安裝了 go 的系統上運作。它已在 Linux、macOS 和 Windows 上進行過測試。

haskell

3.4.0 版新增功能

hook 儲存庫必須有一個或多個 *.cabal 檔案。安裝後,這些套件中的 executable 將可與 entry 一起使用。

這種語言支援 additional_dependencies,因此它可以用作 repo: local hook。

支援:已知 haskell hooks 可以在任何安裝了 cabal 的系統上運作。它已在 Linux、macOS 和 Windows 上進行過測試。

lua

Lua hooks 使用 Luarocks 使用的 Lua 版本安裝。

支援:已知 Lua hooks 可以在任何安裝了 Luarocks 的系統上運作。它已在 Linux 和 macOS 上進行過測試,並且可能可以在 Windows 上運作。

node

hook 儲存庫必須有一個 package.json。它將通過 npm install . 安裝。安裝的套件將提供與 entry 匹配的可執行檔,通常通過 package.json 中的 bin

支援:node hooks 可以在沒有任何系統級依賴項的情況下運作。它已在 Linux、Windows 和 macOS 上進行過測試,並且可能可以在 cygwin 下運作。

perl

Perl hooks 使用 cpan 的系統安裝進行安裝,cpan 是 Perl 附帶的 CPAN 套件安裝程式。

Hook 儲存庫必須包含 cpan 支援的東西,通常是 Makefile.PLBuild.PL,它用於安裝要在 hook 的 entry 定義中使用的可執行檔。儲存庫將通過 cpan -T . 安裝(安裝的檔案儲存在您的 pre-commit 快取中,不會污染其他 Perl 安裝)。

為 Perl 指定 additional_dependencies 時,您可以使用 cpan 理解的任何安裝參數格式

支援:Perl hooks 目前需要預先安裝 Perl,包括 PATH 中的 cpan 工具。它已在 Linux、macOS 和 Windows 上進行過測試。

python

hook 儲存庫必須可通過 pip install . 安裝(通常通過 setup.pypyproject.toml)。安裝的套件將提供與 entry 匹配的可執行檔,通常通過 setup.py 中的 console_scriptsscripts

這種語言也支援 additional_dependencies,因此它可以與 本地 hooks 一起使用。指定的依賴項將會附加到 pip install 命令中。

支援:python hooks 可以在沒有任何系統級依賴項的情況下運作。它已在 Linux、macOS、Windows 和 cygwin 上進行過測試。

r

此 hook 儲存庫必須有一個 renv.lock 檔案,該檔案將在 hook 安裝時使用 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 hooks 就能正常工作。它已在 Linux、macOS 和 Windows 上進行過測試。

ruby

hook 儲存庫必須有一個 *.gemspec。它將通過 gem build *.gemspec && gem install *.gem 安裝。安裝的套件將產生與 entry 匹配的可執行檔,通常通過 gemspec 中的 executables

支援:ruby hooks 可以在沒有任何系統級依賴項的情況下運作。它已在 Linux 和 macOS 上進行過測試,並且可能可以在 cygwin 下運作。

rust

Rust 鉤子使用 Rust 官方套件管理器 Cargo 安裝。

鉤子儲存庫必須有一個 Cargo.toml 檔案,該檔案至少產生一個二進制檔案(範例),其名稱應與鉤子的 entry 定義相符。儲存庫將通過 cargo install --bins 安裝(二進制檔案儲存在您的 pre-commit 快取中,不會污染您的使用者級 Cargo 安裝)。

為 Rust 指定 additional_dependencies 時,您可以使用 {package_name}:{package_version} 語法指定新的程式庫依賴項(用於建構*您的*鉤子儲存庫),或使用特殊語法 cli:{package_name}:{package_version} 指定 CLI 依賴項(單獨建構,二進制檔案可供鉤子使用)。

如果沒有 rust,pre-commit 將會引導它。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

Script 鉤子提供了一種編寫簡單腳本來驗證檔案的方法。entry 應該是相對於鉤子儲存庫根目錄的路徑。

此鉤子類型將不會獲得虛擬環境 – 如果它需要額外的依賴項,則消費者必須手動安裝它們。

支援: script 鉤子的支援取決於腳本本身。

system

System 鉤子提供了一種為系統級可執行檔編寫鉤子的方法,這些可執行檔在上面沒有支援的語言(或者具有不允許它們隔離運行的特殊環境要求,例如 pylint)。

此鉤子類型將不會獲得虛擬環境 – 如果它需要額外的依賴項,則消費者必須手動安裝它們。

支援: system 鉤子的支援取決於可執行檔。

所有 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 [選項]

將 pre-commit 設定自動更新到最新儲存庫版本。

選項

  • --bleeding-edge:更新到預設分支的最前沿,而不是最新的標籤版本(預設行為)。
  • --freeze:在 rev 中儲存「凍結」的雜湊值,而不是標籤名稱。
  • --repo REPO:僅更新此儲存庫。此選項可以指定多次。
  • -j / --jobs:*3.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 [選項]

清除快取的 pre-commit 檔案。

選項:(無其他選項)

pre-commit gc [選項]

清除未使用的快取儲存庫。

pre-commit 會保留已安裝鉤子儲存庫的快取,該快取會隨著時間增長。可以定期運行此命令以從快取目錄中清除未使用的儲存庫。

選項:(無其他選項)

pre-commit init-templatedir 目錄 [選項]

在打算與 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 [選項]

安裝 pre-commit 腳本。

選項

  • -f, --overwrite:將任何現有的 git 鉤子替換為 pre-commit 腳本。
  • --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:以冪等方式將現有的 git 鉤子腳本替換為 pre-commit,並安裝鉤子環境。

如果在命令列上未指定 --hook-typepre-commit install 將從 default_install_hook_types 安裝鉤子。

pre-commit install-hooks [選項]

為可用鉤子安裝所有缺少的環境。除非執行此命令或 install --install-hooks,否則每個鉤子的環境將在第一次調用鉤子時建立。

每個鉤子都在適合鉤子編寫語言的單獨環境中初始化。請參閱 支援的語言

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

選項:(無其他選項)

pre-commit migrate-config [選項]

將清單設定遷移到新的映射設定格式。

選項:(無其他選項)

pre-commit run [hook-id] [選項]

運行鉤子。

選項

  • [hook-id]:指定單個 hook-id 以僅運行該鉤子。
  • -a, --all-files:在儲存庫中的所有檔案上運行。
  • --files [FILES [FILES ...]]:要運行鉤子的特定檔名。
  • --from-ref FROM_REF + --to-ref TO_REF:針對 git 中 FROM_REF...TO_REF 之間更改的檔案運行。
  • --hook-stage 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-receive 鉤子中使用時很有用。

pre-commit sample-config [選項]

產生範例 .pre-commit-config.yaml

選項:(無其他選項)

pre-commit try-repo REPO [選項]

嘗試儲存庫中的鉤子,這對於開發新鉤子很有用。try-repo 也可用於在將儲存庫添加到您的設定之前測試它。try-repo 在運行鉤子之前會根據遠程鉤子儲存庫列印它生成的設定。

選項

  • REPO:必需的可複製鉤子儲存庫。可以是磁碟上的本地路徑。
  • --ref 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 [選項]

卸載 pre-commit 腳本。

選項

  • -t HOOK_TYPE, --hook-type HOOK_TYPE:要卸載的鉤子類型。

以遷移模式運行

預設情況下,如果您有現有的鉤子,pre-commit install 將以遷移模式安裝,該模式會同時運行您現有的鉤子和 pre-commit 的鉤子。要禁用此行為,請將 -f / --overwrite 傳遞給 install 命令。如果您決定不使用 pre-commit,pre-commit uninstall 將把您的鉤子恢復到安裝之前的狀態。

暫時禁用鉤子

並非所有鉤子都是完美的,因此有時您可能需要跳過一個或多個鉤子的執行。 pre-commit 通過查詢 SKIP 環境變數來解決此問題。SKIP 環境變數是以逗號分隔的鉤子 ID 清單。這允許您跳過單個鉤子,而不是 --no-verifying 整個提交。

$ 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 屬性。例如,對於程式碼檢查器或程式碼格式化工具,合理的設定是 stages: [pre-commit, pre-merge-commit, pre-push, manual]

要為特定的 git hooks 安裝 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 hook 類型的預設集。

例如

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 hooks

commit-msg

git commit-msg 文件

commit-msg hooks 將會傳遞一個單一檔案名稱 -- 這個檔案包含要驗證的提交訊息的當前內容。如果存在非零的退出代碼,提交將會中止。

post-checkout

git post-checkout 文件

post-checkout hooks 在 checkout 發生後執行,可用於設定或管理儲存庫中的狀態。

post-checkout hooks 不會操作檔案,因此它們必須設定為 always_run: true,否則它們將會始終被跳過。

環境變數

  • PRE_COMMIT_FROM_REFpost-checkout git hook 的第一個參數
  • PRE_COMMIT_TO_REFpost-checkout git hook 的第二個參數
  • PRE_COMMIT_CHECKOUT_TYPEpost-checkout git hook 的第三個參數

post-commit

git post-commit 文件

post-commit 在提交已經成功後執行,因此它不能用於防止提交發生。

post-commit hooks 不會操作檔案,因此它們必須設定為 always_run: true,否則它們將會始終被跳過。

post-merge

git post-merge 文件

post-merge 在成功執行 git merge 後執行。

post-merge hooks 不會操作檔案,因此它們必須設定為 always_run: true,否則它們將會始終被跳過。

環境變數

  • PRE_COMMIT_IS_SQUASH_MERGEpost-merge git hook 的第一個參數。

post-rewrite

git post-rewrite 文件

post-rewrite 在修改歷史記錄的 git 命令(例如 git commit --amendgit rebase)之後執行。

post-rewrite hooks 不會操作檔案,因此它們必須設定為 always_run: true,否則它們將會始終被跳過。

環境變數

  • PRE_COMMIT_REWRITE_COMMANDpost-rewrite git hook 的第一個參數。

pre-commit

git pre-commit 文件

pre-commit 在提交完成之前觸發,以便對正在提交的程式碼進行檢查。在提交期間對未暫存的變更執行 hooks 可能會導致誤報和漏報。pre-commit 只會在檔案的已暫存內容上執行,方法是在執行 hooks 時暫時儲存未暫存的變更。

pre-merge-commit

git pre-merge-commit 文件

pre-merge-commit 在合併成功後但在建立合併提交之前觸發。這個 hook 會在合併的所有已暫存檔案上執行。

請注意,您需要至少使用 git 2.24 才能使用這個 hook。

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 在 rebase 發生之前觸發。hook 失敗可以取消 rebase 的發生。

pre-rebase hooks 不會操作檔案,因此它們必須設定為 always_run: true,否則它們將會始終被跳過。

環境變數

  • PRE_COMMIT_PRE_REBASE_UPSTREAMpre-rebase git hook 的第一個參數
  • PRE_COMMIT_PRE_REBASE_BRANCHpre-rebase git hook 的第二個參數。

prepare-commit-msg

git prepare-commit-msg 文件

prepare-commit-msg hooks 將會傳遞一個單一檔案名稱 -- 這個檔案可能是空的,也可能包含來自 -m 或其他範本的提交訊息。prepare-commit-msg hooks 可以修改這個檔案的內容來更改將要提交的內容。hook 可能會想要檢查 GIT_EDITOR=:,因為這表示不會啟動編輯器。如果 hook 以非零退出,提交將會中止。

環境變數

  • PRE_COMMIT_COMMIT_MSG_SOURCEprepare-commit-msg git hook 的第二個參數
  • PRE_COMMIT_COMMIT_OBJECT_NAMEprepare-commit-msg git hook 的第三個參數

傳遞參數給 hooks

有時 hooks 需要參數才能正確執行。您可以通過在 .pre-commit-config.yaml 中指定 args 屬性來傳遞靜態參數,如下所示

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

這將會將 --max-line-length=131 傳遞給 flake8

hooks 中的參數模式

如果您正在編寫自己的自定義 hook,您的 hook 應該預期會收到 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

在建立本地 hooks 時,沒有理由將命令參數放入 args 中,因為沒有任何東西可以覆蓋它們 -- 而是將您的參數直接放入 hook 的 entry 中。

例如

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

儲存庫本地 hooks

儲存庫本地 hooks 在以下情況下很有用

  • 腳本與儲存庫緊密耦合,並且將 hook 腳本與儲存庫一起分發是有意義的。
  • Hooks 需要僅存在於儲存庫的構建產物中的狀態(例如 pylint 的應用程式虛擬環境)。
  • 程式碼檢查器的官方儲存庫沒有 pre-commit 中繼資料。

您可以通過將 repo 指定為哨兵 local 來設定儲存庫本地 hooks。

本地 hooks 可以使用任何支援 additional_dependenciesdocker_image / fail / pygrep / script / system 的語言。這使您可以安裝以前需要一個微不足道的鏡像儲存庫才能安裝的東西。

local hook 必須定義 idnamelanguageentryfiles / types,如 建立新的 hooks 中所述。

以下是一個包含一些 local hooks 的範例設定

-   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']

元 hooks

pre-commit 提供了幾個 hooks,它們對於檢查 pre-commit 設定本身很有用。可以使用 repo: meta 啟用這些 hooks。

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

目前可用的 meta hooks

check-hooks-apply

確保設定的 hooks 至少適用於儲存庫中的一個檔案。

check-useless-excludes

確保 exclude 指令適用於儲存庫中的 *任何* 檔案。

identity

一個簡單的 hook,它會印出傳遞給它的所有參數,對於除錯很有用。

在儲存庫上自動啟用 pre-commit

pre-commit init-templatedir 可以用於為 gitinit.templateDir 選項設定一個框架。這意味著任何新複製的儲存庫將會自動設定 hooks,而無需執行 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 的儲存庫時,hooks 都已經設定好了!

$ 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,請使用如下範本 hook(例如在 ~/.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 是為每個 hook 指定的標籤陣列。標籤是通過 identify 庫的一組啟發式方法發現的。選擇 identify 是因為它是一個小型可移植的純 Python 庫。

您將從 identify 中找到的一些常見標籤

  • file
  • symlink
  • directory - 在 pre-commit 的上下文中,這將是一個子模組
  • executable - 檔案是否設定了可執行位元
  • text - 檔案是否看起來像文字檔
  • binary - 檔案是否看起來像二進制檔案
  • 按副檔名 / 命名約定標記
  • 按 shebang (#!) 標記

要發現磁碟上任何檔案的類型,您可以使用 identify 的 cli

$ 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

如果您想要匹配在使用現有 hook 時未包含在 type 中的檔案路徑,則需要還原為僅通過覆蓋 types 設定來匹配 files。以下是如何針對非 json 檔案使用 check-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
            )$

覆蓋語言版本

有時您只想在特定版本的語言上運行 hook。對於每種語言,它們預設使用系統安裝的語言(例如,如果我正在運行 python3.7 且 hook 指定 python,則 pre-commit 將使用 python3.7 運行 hook)。有時您不想要預設的系統安裝版本,因此您可以通過設置 language_version 在每個 hook 的基礎上覆蓋它。

-   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 hook。

特定語言的有效值如下所示

  • python: 您擁有的任何系統安裝的 python 直譯器。此參數的值會作為 -p 傳遞給 virtualenv
    • 在 Windows 上,pep394 名稱將被轉換為 py 啟動器調用,以提高可移植性。因此,即使在 Windows 上,也要繼續使用 python3 (py -3) 或 python3.6 (py -3.6) 等名稱。
  • node: 請參閱 nodeenv
  • ruby: 請參閱 ruby-build
  • rust: language_version 會傳遞給 rustup
  • 3.0.0 版新增 golang: 使用 go.dev/dl 上的版本,例如 1.19.5

您可以在設定檔的 頂層 設定 default_language_version,以控制所有語言 hook 的預設版本。

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 基本目錄規範 使用 $XDG_CACHE_HOME/pre-commit

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 runner 時,這不是預設設置。如果您遇到錯誤 InvalidManifestError,請在您的 [[runner]] 設定中將 builds_dir 設定為靜態內容,例如 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 設定旨在提供可重複且快速的體驗,因此故意不為 hook 儲存庫提供「未鎖定最新版本」的功能。

相反,pre-commit 提供了使用 pre-commit autoupdate 輕鬆升級到最新版本的工具。如果您需要 hook 的絕對最新版本(而不是最新的標記版本),請將 --bleeding-edge 參數傳遞給 autoupdate

pre-commit 假設 rev 的值是一個不可變的引用(例如標記或 SHA),並且將基於該引用進行快取。不支援將分支名稱(或 HEAD)用於 rev 的值,並且它只會表示 hook 安裝時該可變引用的狀態(並且將*不會*自動更新)。

我們正在尋求發展專案並獲得更多貢獻者,尤其是為了支援更多語言/版本。我們還希望將 .pre-commit-hooks.yaml 檔案添加到熱門的程式碼檢查器中,而無需維護分支/鏡像。

歡迎提交錯誤報告、拉取請求和功能請求。

贊助

如果您或您的公司想支援 pre-commit 的開發,可以通过以下方式做出貢獻

取得協助

有幾種方法可以取得 pre-commit 的協助

貢獻者