pre-commit

複数言語に対応したpre-commitフックの管理と保守のためのフレームワークです。

スター
pre-commit logo

Gitフックスクリプトは、コードレビューに提出する前に単純な問題を特定するために役立ちます。当社のフックは、コミットごとに実行され、セミコロンの欠落、末尾の空白、デバッグステートメントなど、コードの問題を自動的に指摘します。コードレビューの前にこれらの問題を指摘することで、コードレビューアーは些細なスタイルの修正に時間を無駄にすることなく、変更のアーキテクチャに集中できます。

より多くのライブラリとプロジェクトを作成するにつれて、プロジェクト間でpre-commitフックを共有することが困難であることに気づきました。私たちは扱いにくいbashスクリプトをプロジェクト間でコピーアンドペーストし、異なるプロジェクト構造に合わせてフックを手動で変更する必要がありました。

業界標準の最高のリンターを使用するべきだと考えています。最高のリンターの中には、プロジェクトで使用していない言語やマシンにインストールされていない言語で記述されているものもあります。たとえば、scss-lintはRubyで記述されたSCSS用のリンターです。Nodeでプロジェクトを作成している場合でも、プロジェクトにGemfileを追加したり、scss-lintのインストール方法を理解したりすることなく、scss-lintをpre-commitフックとして使用できるはずです。

フックの問題を解決するためにpre-commitを構築しました。これは、pre-commitフックのための複数言語対応のパッケージマネージャーです。必要なフックのリストを指定すると、pre-commitは、すべてのコミットの前に、あらゆる言語で記述されたフックのインストールと実行を管理します。pre-commitは、特にrootアクセスを必要としないように設計されています。開発者の1人がNodeをインストールしていないがJavaScriptファイルを修正した場合、pre-commitは自動的にNodeをダウンロードしてビルドし、rootアクセスなしでeslintを実行します。

フックを実行する前に、pre-commitパッケージマネージャーをインストールする必要があります。

pipの使用

pip install pre-commit

Pythonプロジェクトでは、次の行をrequirements.txt(またはrequirements-dev.txt)に追加します。

pre-commit

0依存性のzipappとして

  • githubリリースから.pyzファイルをダウンロードして配置します。
  • pre-commit ...の代わりにpython pre-commit-#.#.#.pyz ...を実行します。

クイックスタート

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
  • これで、git commitpre-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プラグインを追加するには、.pre-commit-config.yaml設定ファイルを使用します。

プロジェクトのルートに.pre-commit-config.yamlという名前のファイルを追加します。pre-commit設定ファイルは、インストールされるリポジトリとフックを記述します。

.pre-commit-config.yaml - トップレベル

repos

リポジトリマッピングのリスト。

default_install_hook_types

(オプション: デフォルトは[pre-commit]) pre-commit installの実行時にデフォルトで使用される--hook-typeのリスト。

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) 最初の失敗後にpre-commitがフックの実行を停止するようにするにはtrueに設定します。

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などのフックのプラグインをインストールするのに役立つアプリケーションの1つです。

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に指示する.pre-commit-hooks.yamlファイルが含まれている必要があります。

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

フックリポジトリには、conda env create --file environment.yml ...を使用して環境を作成するために使用されるenvironment.ymlファイルが含まれている必要があります。

conda言語はadditional_dependenciesもサポートしており、値をconda installに直接渡します。そのため、この言語はローカルフックで使用できます。

PRE_COMMIT_USE_MAMBA=1またはPRE_COMMIT_USE_MICROMAMBA=1環境変数を使用して、代わりにmambaまたはmicromambaを使用できます。

サポート: システムにcondaバイナリ(minicondaなど)がインストールされている限り、condaフックは機能します。Linux、macOS、Windowsでテスト済みです。

coursier

フックリポジトリには.pre-commit-channelフォルダが必要です。このフォルダには、フックをインストールするためのcoursier アプリケーション記述子が含まれている必要があります。coursierフックの設定では、entryはリポジトリの.pre-commit-channelフォルダからインストールされた実行可能ファイルに対応する必要があります。

サポート: coursierフックは、csまたはcoursierパッケージマネージャーがインストールされているシステムであれば動作することが確認されています。インストールする特定の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: dartadditional_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のシステムインストールを使用してインストールされます。

フックリポジトリには、この例のようにpackしてinstallできるdotnet CLIツールが含まれている必要があります。entryは、リポジトリをビルドして作成された実行可能ファイルと一致する必要があります。追加の依存関係は現在サポートされていません。

サポート: dotnetフックは、dotnet CLIがインストールされているシステムであれば動作することが確認されています。LinuxとWindowsでテスト済みです。

fail

ファイル名を指定してファイルを禁止するための軽量なlanguageです。fail言語は、ローカルフックに特に役立ちます。

entryは、フックが失敗したときに表示されます。nameに簡単な説明を、entryに詳細な修正手順を提供することをお勧めします。

changelogディレクトリに追加されるファイルは、.rstで終わるファイルを除いてすべて防止する例を以下に示します。

-   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を作成し、entryGOPATHbinディレクトリにインストールされる実行可能ファイルと一致する必要があります。

この言語はadditional_dependenciesをサポートしており、値をgo installに直接渡します。repo: localフックとして使用できます。

2.17.0での変更: 以前はgo get ./...が使用されていました。

3.0.0の新機能: pre-commitは、存在しない場合はgoをブートストラップします。language: golangは、language_versionもサポートするようになりました。

サポート: golangフックは、goがインストールされているシステムであれば動作することが確認されています。Linux、macOS、Windowsでテスト済みです。

haskell

3.4.0の新機能

フックリポジトリには、1つ以上の*.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フックは、Perlに付属するCPANパッケージインストーラーであるcpanのシステムインストールを使用してインストールされます。

フックリポジトリには、cpanがサポートする何か(通常はMakefile.PLまたはBuild.PL)が必要です。これを使用して、フックのentry定義で使用できる実行可能ファイルをインストールします。リポジトリはcpan -T .を使用してインストールされます(インストールされたファイルはpre-commitキャッシュに保存され、他のPerlインストールを汚染しません)。

Perlのadditional_dependenciesを指定する場合は、cpanが理解するインストール引数の形式を使用できます。

サポート: Perlフックには現在、PATHcpanツールを含む既存のPerlインストールが必要です。Linux、macOS、Windowsでテスト済みです。

python

フックリポジトリはpip install .を使用してインストール可能である必要があります(通常はsetup.pyまたはpyproject.tomlによって)。インストールされたパッケージは、entryと一致する実行可能ファイルを提供します(通常はsetup.pyconsole_scriptsまたはscriptsを介して)。

この言語はadditional_dependenciesもサポートしているので、ローカルフックで使用できます。指定された依存関係はpip installコマンドに追加されます。

サポート: pythonフックは、システムレベルの依存関係なしで動作します。Linux、macOS、Windows、cygwinでテスト済みです。

r

このフックリポジトリには、フックインストール時にrenv::restore()で復元されるrenv.lockファイルが必要です。リポジトリがRパッケージの場合(つまり、DESCRIPTIONType: Packageがある場合)、インストールされます。entryでサポートされる構文はRscript -e {expression}またはRscript path/relative/to/hook/rootです。すべての設定はargsを介して公開されるべきであり、最大の透明性と移植性を確保するために、Rの起動プロセスはスキップされます(--vanillaをエミュレートします)。

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フックは、Rustの公式パッケージマネージャーであるCargoを使用してインストールされます。

フックリポジトリには、少なくとも1つのバイナリ()を作成するCargo.tomlファイルが必要です。その名前は、フックのentry定義と一致する必要があります。リポジトリはcargo install --binsを使用してインストールされます(バイナリはpre-commitキャッシュに保存され、ユーザーレベルのCargoインストールを汚染しません)。

Rustのadditional_dependenciesを指定する際には、新しいライブラリ依存関係(あなたのフックリポジトリの構築に使用)を指定するために{package_name}:{package_version}構文、またはCLI依存関係(個別に構築され、フックで使用できるバイナリが作成される)のためにcli:{package_name}:{package_version}特殊構文を使用できます。

pre-commitは、存在しない場合はrustをブートストラップします。language: rustlanguage_versionもサポートしています。

サポート:Linux、Windows、macOSでテスト済みです。

swift

フックリポジトリにはPackage.swiftが必要です。これはswift build -c releaseを使用してインストールされます。entryは、リポジトリのビルドによって作成された実行可能ファイルと一致する必要があります。

サポート:swiftフックは、swiftがインストールされているシステムであれば動作することがわかっています。LinuxとmacOSでテスト済みです。

pygrep

grepのクロスプラットフォームPython実装—pygrepフックは、ファイルの一致によってコミットを防止する単純なフックをすばやく作成する方法です。正規表現をentryとして指定します。entryは、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:既存の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-typeが指定されていない場合、pre-commit installdefault_install_hook_typesからフックをインストールします。

pre-commit install-hooks [options]

利用可能なフックのすべての不足している環境をインストールします。このコマンドまたはinstall --install-hooksが実行されない限り、各フックの環境はフックが最初に呼び出されたときに作成されます。

各フックは、フックが記述されている言語に適した個別の環境で初期化されます。サポートされている言語を参照してください。

このコマンドは、pre-commitスクリプトをインストールしません。1つのコマンドでフック環境と一緒にスクリプトをインストールするには、pre-commit install --install-hooksを使用します。

オプション:(追加オプションはありません)

pre-commit migrate-config [options]

リスト設定を新しいマップ設定形式に移行します。

オプション:(追加オプションはありません)

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

フックを実行します。

オプション

  • [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 HEADHEAD^^^HEADの間で変更されたファイルに対して実行します。この形式は、pre-receiveフックで使用する場合に便利です。

pre-commit sample-config [options]

サンプルの.pre-commit-config.yamlを作成します。

オプション:(追加オプションはありません)

pre-commit try-repo REPO [options]

リポジトリ内のフックを試します。これは、新しいフックを開発する場合に役立ちます。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-hookspre-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を参照して、pre-commit try-repoでもサポートされている、より便利なrun呼び出しを確認してください。

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でインストール前の状態にフックを復元します。

フックの一時的な無効化

すべてのフックが完璧なわけではないため、場合によっては、1つ以上のフックの実行をスキップする必要がある場合があります。pre-commitは、SKIP環境変数をクエリすることでこれを解決します。SKIP環境変数は、フックIDのカンマ区切りのリストです。これにより、コミット全体を--no-verifyする代わりに、単一のフックをスキップできます。

$ SKIP=flake8 git commit -m "foo"

特定のステージでのフックの実行の制限

pre-commitは、多くの異なる種類のgitフックをサポートしています(pre-commitだけではありません!)。

フックのプロバイダーは、.pre-commit-hooks.yamlstagesプロパティを設定することで、実行するgitフックを選択できます。これは、.pre-commit-config.yamlstagesを設定することで上書きすることもできます。これらのいずれにも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フックに対してpre-commitをインストールするには、pre-commit install--hook-typeを渡します。これは、次のように複数回指定できます。

$ 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_REF: post-checkout gitフックへの最初の引数
  • PRE_COMMIT_TO_REF: post-checkout gitフックへの2番目の引数
  • PRE_COMMIT_CHECKOUT_TYPE: post-checkout gitフックへの3番目の引数

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_MERGE: post-merge gitフックへの最初の引数。

post-rewrite

git post-rewrite ドキュメント

post-rewriteは、git commit --amendgit rebaseなど、履歴を変更するgitコマンドの後で実行されます。

post-rewriteフックはファイル上で動作しないため、always_run: trueとして設定する必要があります。そうでない場合、常にスキップされます。

環境変数

  • PRE_COMMIT_REWRITE_COMMAND: post-rewrite gitフックへの最初の引数。

pre-commit

git pre-commit ドキュメント

pre-commitは、コミットが確定される前にトリガーされ、コミットされるコードをチェックできます。ステージされていない変更に対してフックを実行すると、コミット中に偽陽性と偽陰性の両方が発生する可能性があります。pre-commitは、フックの実行中にステージされていない変更を一時的にstashすることで、ステージされたファイルの内容のみを実行します。

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_UPSTREAM: pre-rebase gitフックへの最初の引数。
  • PRE_COMMIT_PRE_REBASE_BRANCH: pre-rebase gitフックへの2番目の引数。

prepare-commit-msg

git prepare-commit-msg ドキュメント

prepare-commit-msgフックには、単一のファイル名が渡されます。このファイルは空の場合もあれば、-mまたはその他のテンプレートからのコミットメッセージが含まれている場合もあります。prepare-commit-msgフックは、このファイルの内容を変更してコミットする内容を変更できます。フックはGIT_EDITOR=:をチェックする必要がある場合があります。これは、エディターが起動されないことを示しています。フックがゼロ以外の値で終了した場合、コミットは中止されます。

環境変数

  • PRE_COMMIT_COMMIT_MSG_SOURCE: prepare-commit-msg gitフックへの2番目の引数。
  • PRE_COMMIT_COMMIT_OBJECT_NAME: prepare-commit-msg gitフックへの3番目の引数。

フックへの引数の渡し

場合によっては、フックが正しく実行するために引数が必要になります。.pre-commit-config.yamlargsプロパティを次のように指定することで、静的な引数を渡すことができます。

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

これにより、--max-line-length=131flake8に渡されます。

フックにおける引数のパターン

独自のカスタムフックを作成する場合は、フックは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$

リポジトリローカルフック

リポジトリローカルフックは、次の場合に役立ちます。

  • スクリプトがリポジトリに密接に結合されており、フックスクリプトをリポジトリと共に配布することが理にかなっています。
  • フックには、リポジトリの構築済みアーティファクト(pylintの場合はアプリのvirtualenvなど)にのみ存在する状態が必要です。
  • リンターの公式リポジトリにpre-commitのメタデータがありません。

repoをセントリーlocalとして指定することで、リポジトリローカルフックを構成できます。

ローカルフックは、additional_dependenciesまたはdocker_image / fail / pygrep / script / systemをサポートする言語を使用できます。これにより、以前は些細なミラーリポジトリが必要だったものをインストールできます。

localフックは、新しいフックの作成で指定されているように、idnamelanguageentry、およびfiles / 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

構成されたフックがリポジトリ内の少なくとも1つのファイルに適用されることを確認します。

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による従来のフィルタリングよりもいくつかの利点があります。

  • エラーが発生しやすい正規表現を使用しない
  • ファイルは、シェバンで照合できます(拡張子がなくても)。
  • シンボリックリンク/サブモジュールを簡単に無視できます。

typesは、フックごとにタグの配列として指定されます。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_or、および files は、フィルタリング時に 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 の正規表現がサポートする機能をすべて使用できます。

除外/包含する項目のリストが長いために正規表現が扱いにくくなった場合は、verbose 正規表現が役立つ場合があります。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 インタープリターです。この引数の値は、virtualenv-p として渡されます。
    • Windows では、PEP 394 の名前は移植性のために py ランチャー呼び出しに変換されます。そのため、Windows でも python3 (py -3) や python3.6 (py -3.6) のような名前を引き続き使用してください。
  • node: nodeenv を参照してください。
  • ruby: ruby-build を参照してください。
  • rust: language_versionrustup に渡されます。
  • 3.0.0 で新規追加 golang: go.dev/dl1.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 は継続的インテグレーションツールのとしても使用できます。たとえば、CI ステップとして pre-commit run --all-files を追加すると、すべてが最適な状態に保たれます。変更されたファイルのみを確認するには、pre-commit run --from-ref origin/HEAD --to-ref HEAD のように使用します(高速化に繋がります)。

CI キャッシュの管理

pre-commit はデフォルトでリポジトリストアを ~/.cache/pre-commit に配置します。これは2つの方法で設定できます。

  • PRE_COMMIT_HOME: 設定されている場合、pre-commit は代わりにその場所を使用します。
  • XDG_CACHE_HOME: 設定されている場合、pre-commit は XDG Base Directory Specification に従って $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 のハッシュをキャッシュキーに含める必要があります。リポジトリテンプレートについては、[メールアドレスを保護する] を参照してください。

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 Actions を参照してください。

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 エラーが発生する場合は、[[runner]] 構成で builds_dir を静的なもの(例: builds_dir = "/builds")に設定してください。

Travis CI の例

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

tox との併用

tox は、pre-commit などのテスト/CI ツールの構成に役立ちます。tox>=2 の機能の1つは、環境変数をクリアしてテストの再現性を高めることです。状況によっては、pre-commit にはいくつかの環境変数が必要になるため、それらをそのまま渡す必要があります。

SSH を介してリポジトリをクローンする場合 (repo: [メールアドレスを保護する]:...)、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 に以下を追加します。

[testenv]
passenv = SSH_AUTH_SOCK

同様に、http/https を介してリポジトリをクローンする場合 (repo: https://github.com:...)、企業の http(s) プロキシサーバーの背後で作業している可能性があり、その場合、githttp_proxyhttps_proxyno_proxy 変数を設定する必要があります。そうでないと、クローンが失敗する可能性があります。

[testenv]
passenv = http_proxy https_proxy no_proxy

リポジトリの最新バージョンを使用する

pre-commit の設定は、再現性が高く高速なエクスペリエンスを提供することを目的としているため、フックリポジトリの「固定されていない最新バージョン」機能は意図的に提供されていません。

代わりに、pre-commitpre-commit autoupdate を使用して最新バージョンに簡単にアップグレードするためのツールを提供します。タグ付けされた最新バージョンではなく、絶対的に最新のフックバージョンが必要な場合は、autoupdate--bleeding-edge パラメーターを渡します。

pre-commit は、rev の値が不変の参照(タグや SHA など)であると想定し、それに基づいてキャッシュします。rev の値にブランチ名(または HEAD)を使用することはサポートされておらず、フックのインストール時のその可変参照の状態のみを表し、自動的には更新されません

私たちはプロジェクトの成長と、特により多くの言語/バージョンをサポートするための貢献者の獲得を目指しています。また、フォーク/ミラーを維持することなく、一般的なリンターに .pre-commit-hooks.yaml ファイルを追加したいと考えています。

バグレポート、プルリクエスト、機能リクエストを自由に送信してください。

スポンサーシップ

あなたまたはあなたの会社が pre-commit の開発を支援したい場合は、次の方法で貢献できます。

ヘルプの入手

pre-commit のヘルプを入手するには、いくつかの方法があります。

貢献者