Pythonのpre-commitは、Gitのpre-commitフックを簡単に管理するためのモジュールです。pre-commitを使用すれば、Git管理下のファイルを編集した際にflake8やblackといったリンター・フォーマッターを適用したり、秘密鍵が管理下に含まれていないかなどの様々な処理を簡単にフックに登録することができます。
基本的な使い方
インストール
まず、pre-commitはpip
コマンドでインストールできます。
$ pip install pre-commit
インストールできたら、pre-commit
というコマンドが使用できるようになります。
$ pre-commit --version
pre-commit 2.17.0
設定ファイルの作成
サンプルの設定ファイルはコマンドで作成することができます。設定ファイルの書き方については後述します。
$ pre-commit sample-config > .pre-commit-config.yaml
$ cat .pre-commit-config.yaml
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
フックの登録
まず、説明のためにGitリポジトリを新たに作成します。
$ git init
Initialized empty Git repository in (PATH/TO/YOUR/REPOSITORY)
後は、Gitリポジトリの中でpre-commit install
サブコマンドでフックを登録できます。
$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
ソースファイルのコミット
それでは、簡単なソースファイルをコミットしてみましょう。なお、敢えて末尾に空白を入れてみます。
$ echo "print(1) " > sample.py
$ git add sample.py
$ git add .pre-commit-config.yaml
$ git commit -m "first commit"
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[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...
Trim Trailing Whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook
Fixing sample.py
Fix End of Files.........................................................Passed
Check Yaml...............................................................Passed
Check for added large files..............................................Passed
するとtrailing-whitespace
フックによってsample.py
に問題が見つかりました。git log
サブコマンドで確認すると、コミット自体が中断されていることがわかります。
$ git log
fatal: your current branch 'master' does not have any commits yet
また、trailing-whitespace
はフォーマッター機能であるため、自動的にsample.py
の修正まで行ってくれます。WEBページ上では表現しにくいですが、お手元で実行すれば末尾の空白が消えていることが確認できるはずです。
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .pre-commit-config.yaml
new file: sample.py
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: sample.py
後は再度、変更を追加してコミットすれば完了です。
$ git add sample.py
$ git commit -m "first commit"
Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Passed
Check Yaml...............................................................Passed
Check for added large files..............................................Passed
[master (root-commit) 7f50631] first commit
2 files changed, 11 insertions(+)
create mode 100644 .pre-commit-config.yaml
create mode 100644 sample.py
$ git log
commit 7f506317da543561a1303bc9f903c8232ecbee78 (HEAD -> master)
Author: author <you@example.com>
Date: Fri Feb 18 20:36:22 2022 +0900
first commit
なお、各種フックは差分をコミットするファイルにのみ適用されます。
サブコマンド群
autoupdateサブコマンド
pre-commit autoupdate
サブコマンドは、設定ファイルで管理されているフックのリポジトリを最新化します。
$ pre-commit autoupdate
Updating https://github.com/pre-commit/pre-commit-hooks ... [INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
updating v3.2.0 -> v4.1.0.
$ cat .pre-commit-config.yaml
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
runサブコマンド
pre-commit run
サブコマンドは、フックを手動で実行します。対象のファイルはコミット時と同様に差分を追加したファイルのみですが、--all-files
オプションでGit管理下の全てのファイルを対象としたり、--files
オプションで特定のファイルを対象にしたりすることができます。Git管理されていないファイルは対象になりません。
$ echo "print(1) " > sample.py
$ pre-commit run -a
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook
Fixing sample.py
fix end of files.........................................................Passed
check yaml...............................................................Passed
check for added large files..............................................Passed
$ echo "print(1) " > sample_new.py
$ pre-commit run -a
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check yaml...............................................................Passed
check for added large files..............................................Passed
uninstallサブコマンド
pre-commit uninstall
サブコマンドは、Gitリポジトリの管理下のフックを削除します。
オススメのフックと設定方法
この節ではオススメのフックを紹介します。設定方法は、各小節のYAMLコードを.pre-commit-config.yaml
に追加するだけです。
なお、フックのリビジョンを最新化する場合は、手動で書き換えるか、設定ファイルの更新後にpre-commit autoupdate
を実行してください。
black
blackはコードフォーマッターの一つです。設定項目が非常に少なく、改行の仕方やシングルクォート・ダブルクォートの使い分けなど、書き方の揺らぎを強制的に統一してしまうという特徴があります。フォーマットの好みに関する議論を回避して、一通りの書き方に統一してしまいたい場合にオススメです。
repos:
# 中略
- repo: https://github.com/psf/black
rev: 22.1.0
hooks:
- id: black
Bandit
Banditはセキュリティリスクのあるコードを検知してくれるツールです。
- repo: https://github.com/PyCQA/bandit
rev: 1.7.2
hooks:
- id: bandit
バージョン情報
筆者は以下のバージョンで動作を確認しました。
- pre-commit==2.17.0