pre-commitとは?「使い方」や「.pre-commit-config.yaml」の設定例を解説!

チームで開発していると、こんな経験はありませんか?

  • コミットしたあとにCIの静的解析でエラーになった
  • ローカルでLintを実行するのを忘れていた
  • プルリクエストを出したあとに、単純なミスを指摘された

こうしたミスを、コミットする前に見つけるために便利なのが「pre-commit」です。

pre-commitを使うと、Gitでコミットする直前にLintやコードチェックなどを自動で実行できます。

そのため、「コミットしてからミスに気づく」のではなく、「コミットする前にミスに気づくという仕組みを作ることができます。

この記事では、pre-commitとは何なのか、基本的な使い方、.pre-commit-config.yamlの設定例などわかりやすく解説します。

pre-commitとは?

pre-commitは、Gitでコミットする前に、コードのチェックや整形などを自動で実行できるツールです。

例えば、コミットする前に次のような処理を自動で実行できます。

  • コードを自動で整形する
  • Lintを実行する
  • 不要な空白を削除する
  • ファイルの最後に改行があるか確認する
  • YAMLやJSONの構文をチェックする
  • タイポ(スペルミス)をチェックする

pre-commitは、Gitに備わっているGitフックという仕組みを利用しています。

Gitフックとは?

Gitフックとは、Gitで特定の操作をしたタイミングで、自動的に処理を実行できる仕組みです。

コミットする前やプッシュする前などのタイミングで自動的に処理を実行できます。

例えば、

git commit -m "機能を追加"

を実行すると、実際にコミットされる前に、pre-commitで設定したチェックが自動的に実行されます。

チェックに問題がなければ、そのままコミットされます。一方、問題が見つかった場合はコミットが中止されたり、設定したツールによってファイルが自動修正されたりします。

そのため、「Lintを実行するのを忘れていた」といった単純なミスを減らすことができます。

pre-commitを利用するメリット

pre-commitを利用する主なメリットは、次のとおりです。

  • コミット前にLintやコード整形を自動実行できる
  • チェックの実行忘れを防ぎやすい
  • チームで同じチェック設定を共有できる
  • 単純なミスをレビュー前に発見できる
  • 修正コミットやレビューの手戻りを減らせる

特にチーム開発では、.pre-commit-config.yamlをGitで管理しておくことで、メンバー間で同じ設定を共有できます(後ほど.pre-commit-config.yamlについて解説します)。

pre-commitの使い方

pre-commitを利用する基本的な流れは、次のとおりです。

  • pre-commitをインストールする
  • .pre-commit-config.yamlを作成する
  • コミット前に実行したい処理を設定する
  • pre-commit installを実行する
  • 通常どおりGitでコミットする

順番に見ていきましょう。

pre-commitをインストールする

まずは、pre-commitをインストールします。

pipを利用する場合は、次のコマンドを実行します。

pip install pre-commit

macOSでHomebrewを利用している場合は、次の方法でもインストールできます。

brew install pre-commit

インストールできたか確認してみましょう。

pre-commit --version

バージョンが表示されればインストール完了です。

.pre-commit-config.yamlを作成する

次に、Gitリポジトリのルートディレクトリに、.pre-commit-config.yamlという設定ファイルを作成します。

例えば、次のような構成です。

sample-project/
├── .git/
├── .pre-commit-config.yaml   # これを作成!!
├── src/
└── README.md

.pre-commit-config.yamlには、コミット前に実行したい処理を設定します。

例えば、次のように記述します。

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer

この例では、次の2つの処理を設定しています。

  • 行末の不要な空白を削除する(trailing-whitespace
  • ファイルの末尾が適切な改行で終わるように整える(end-of-file-fixer

pre-commit installを実行する

.pre-commit-config.yamlを作成したら、プロジェクトのルートディレクトリで次のコマンドを実行します。

pre-commit install

実行すると、次のようなメッセージが表示されます。

pre-commit installed at .git/hooks/pre-commit

これで、pre-commitがGitのコミット前に自動で実行されるように設定されました(正確には、Gitのpre-commitフックとして登録されました)。

以降はGitでコミットを実行すると、コミットされる直前にpre-commitが自動的に実行されます。

あとは通常どおりコミットするだけです。

git add .
git commit -m "ファイルを更新"

コミットする直前に、.pre-commit-config.yamlで設定した処理が自動的に実行されます。

実行結果の例を以下に示します。

$ git commit -m "ファイルを更新"
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
[main 5d1b0cf] ファイルを更新
 1 file changed, 1 insertion(+), 1 deletion(-)

なお、pre-commitを初めて実行するときは、設定したフックを実行するための環境が自動的に作成されます。そのため、初回のコミットでは次のようなメッセージが表示され、通常より少し時間がかかることがあります。

$ git commit -m "ファイルを更新"
[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...
[main 5d1b0cf] ファイルを更新
 1 file changed, 1 insertion(+), 1 deletion(-)

手動でpre-commitを実行する

pre-commitは、コミットするときだけでなく、手動で実行することもできます。

すべてのファイルを対象にチェックしたい場合は、次のコマンドを実行します。

pre-commit run --all-files

pre-commitを初めて導入したときなどに、プロジェクト全体をまとめてチェックできるので便利です。

.pre-commit-config.yamlの例

まずは、1つのhookだけを設定するシンプルな例を見てみましょう。

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

trailing-whitespaceは、行末にある不要な空白を自動で削除するhookです。

.pre-commit-config.yamlでは、以下に示すようにhookを複数まとめて設定することもできます。

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: check-added-large-files

それぞれのhookには、次のような役割があります。

  • end-of-file-fixer
    • ファイルの末尾が適切な改行で終わるように整える。
  • check-yaml
    • YAMLファイルの構文に問題がないかチェックする。
  • check-json
    • JSONファイルの構文に問題がないかチェックする。
  • check-added-large-files
    • 大きなファイルを誤ってGitに追加してしまうのを防ぐ。

利用できるhookの一覧は、pre-commit-hooksのGitHubリポジトリで確認できます。

タイポをチェックする

スペルミスをチェックしたい場合は、typosというツールも利用できます。

ここまでの例では、pre-commit-hooksに用意されているhookを使っていたため、repoには次のURLを指定していました。

repo: https://github.com/pre-commit/pre-commit-hooks

一方、typospre-commit-hooksに含まれているhookではなく、別のツールです。そのため、repoにはtyposを公開しているGitHubリポジトリを指定します。

repos:
  - repo: https://github.com/crate-ci/typos
    rev: v1.49.0
    hooks:
      - id: typos

このように、repoには、利用したいhookが公開されているリポジトリを指定します。今回の場合は、typosを利用するため、https://github.com/crate-ci/typosを指定しています。

例えば、「seperate」のようなスペルミスがあると、以下に示すように、コミットする前にスペルミスを検出し、修正可能なものは自動で修正してくれます。

$ git commit -m "ファイルを更新"
typos....................................................................Failed
- hook id: typos
- files were modified by this hook

pre-commitでの設定方法は、typosの公式ドキュメントに記載されています。

複数のツールを組み合わせる

実際のプロジェクトでは、1つのhookだけではなく、複数のhookやツールを組み合わせて利用することが多いです。

例えば、次のように設定できます。

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: check-added-large-files

  - repo: https://github.com/crate-ci/typos
    rev: v1.49.0
    hooks:
      - id: typos

このように、同じrepoのhookは1つにまとめて書き、別のツールを使う場合だけ新しいrepoを追加すると、.pre-commit-config.yamlをすっきり書くことができます。

プロジェクト内の独自hookを利用する

ここまでは、GitHubなどで公開されているhookを利用する方法を紹介しました。

一方、pre-commitでは、自分のプロジェクト内にあるスクリプトやコマンドをhookとして実行することもできます。

その場合は、repoにURLではなくlocalを指定します。

例えば、プロジェクト内にあるPythonのLintスクリプトをコミット前に実行したい場合は、次のように設定できます。

repos:
  - repo: local
    hooks:
      - id: my-lint
        name: Run my lint
        entry: python scripts/lint.py
        language: system
        types: [python]

この設定では、コミット対象にPythonファイルが含まれている場合に、scripts/lint.pyが自動的に実行されます。例えば対象がsample.pyの場合、イメージとしては、

python scripts/lint.py sample.py

のように実行されます。

それぞれの項目の意味は、次のとおりです。

項目意味
repo: local外部のGitHubリポジトリではなく、プロジェクト内のhookを利用する。
idhookを識別するための名前。
namepre-commit実行時に画面に表示される名前。
entry実際に実行するコマンド。scripts/lint.pyを実行している。
languageコマンドをどの環境で実行するか。systemの場合はシステムにインストールされているコマンドを使用する。
types対象にするファイルの種類。今回はPythonファイルを対象としている。

たとえば、

name: Run my lint

なら、実行時にはだいたい次のように表示されます。

Run my lint........................................Passed

本記事のまとめ

この記事では『pre-commit』について、以下の内容を説明しました。

  • pre-commitとは何か
  • pre-commitの基本的な使い方
  • .pre-commit-config.yamlの設定方法
  • 複数のhookやツールを組み合わせる方法
  • プロジェクト独自のhookを実行する方法

pre-commitを利用すると、コミットする前にLintやコードチェックなどを自動で実行できます。

チェックの実行忘れや単純なミスを減らせるため、特にチーム開発では便利なツールです。

お読みいただきありがとうございました。

スポンサーリンク