はじめに
このガイドでは、Gitコミット時に自動でコードの整形(フォーマット)や静的解析を行うためのツール「pre-commit」の導入方法について、初心者の方にも分かりやすく解説します。
pre-commitとは?
pre-commit
は、Gitの「フック」という仕組みを利用して、コミットを行う直前に特定の処理を自動で実行するためのフレームワークです。これはオープンソースで開発されており、Pythonコミュニティを中心に、多くのプロジェクトでコード品質の維持に活用されています。
pre-commitの仕組み
pre-commit
は、Gitのクライアントサイドフックの一つであるpre-commit
フックを利用します。このフックは、git commit
コマンドが実行された際に、コミットメッセージの編集画面が表示される前に自動で実行されます。
-
Gitフックのインストール:
pre-commit install
コマンドを実行すると、.git/hooks/pre-commit
というスクリプトが作成されます。このスクリプトが、実際のpre-commit
の処理を呼び出します。 -
設定ファイルの読み込み: コミットが実行されると、
pre-commit
はプロジェクトルートにある.pre-commit-config.yaml
ファイルを読み込み、定義されたフック(チェック処理)のリストを取得します。 -
仮想環境の作成とツールのインストール: 各フックは、それぞれ独立した仮想環境(Pythonの
venv
やNode.jsのnodeenv
など)内で実行されます。これにより、プロジェクトの依存関係とフックが使用するツールの依存関係が衝突するのを防ぎます。フックが初めて実行される際には、必要なツールがこの仮想環境内に自動でインストールされます。 - フックの実行: 定義されたフックが順番に実行されます。通常、フックはコミット対象のファイル(ステージングエリアにあるファイル)に対して処理を行います。
- 結果の判定: すべてのフックが成功(終了コード0)した場合のみ、コミットプロセスが続行されます。一つでもフックが失敗(終了コードが0以外)した場合、コミットは中断され、エラーメッセージが表示されます。
この仕組みにより、開発者はコミット前にコードの問題を自動で検出し、修正することができます。これにより、不完全なコードやスタイル違反のあるコードがリポジトリに混入するのを防ぎ、チーム全体のコード品質を向上させます。
なぜpre-commitを使うのか?(メリット・デメリット)
メリット
- コード品質の向上: コミット前に自動でコードチェックを行うことで、バグの混入を防ぎ、コードの品質を高く保つことができます。
- コードスタイルの統一: チーム内で統一されたコードスタイルを強制することで、誰が書いても読みやすいコードベースを維持できます。
- レビューコストの削減: 人間によるコードレビューの前に基本的なチェックが自動で行われるため、レビュー担当者の負担を減らすことができます。
- 開発体験の向上: 開発者は、手動でフォーマッターやリンターを実行する手間が省け、コードの品質に関するフィードバックを即座に得られます。
-
CI/CDとの連携:
pre-commit
フックでパスするコードは、CI/CDパイプラインでもパスする可能性が高く、CI/CDの失敗を減らすことができます。
デメリット
-
初期設定の手間: プロジェクトに初めて導入する際や、新しいフックを追加する際には、設定ファイル(
.pre-commit-config.yaml
)の記述やツールのインストールに多少の手間がかかります。 - コミット速度の低下: フックの数や処理内容によっては、コミットにかかる時間が長くなることがあります。特に、初めてフックを実行する際の環境構築には時間がかかる場合があります。
-
学習コスト:
pre-commit
の概念やYAMLファイルの書き方など、ある程度の学習が必要です。 - 強制力: コードの品質を保つ上でメリットとなる強制力ですが、開発者によっては煩わしいと感じる場合もあります。
導入手順
ステップ1: pre-commit
のインストール
まず、pre-commit
をプロジェクトの依存関係に追加し、インストールします。
-
requirements.txt
の編集:
プロジェクトのルートディレクトリにあるrequirements.txt
ファイルに、以下の行を追加します。pre-commit
これにより、プロジェクトに必要なPythonパッケージとして
pre-commit
が指定されます。 -
依存関係のインストール:
requirements.txt
を編集したら、以下のコマンドを実行して、プロジェクトの依存関係をインストールします。pip install -r requirements.txt
このコマンドにより、
pre-commit
を含むすべての必要なパッケージが仮想環境にインストールされます。
ステップ2: .pre-commit-config.yaml
の作成
次に、pre-commit
がどのようなチェックを行うかを定義する設定ファイルを作成します。プロジェクトのルートディレクトリに.pre-commit-config.yaml
という名前でファイルを作成し、以下の内容を記述してください。
YAMLファイルの基本的な書き方
.pre-commit-config.yaml
はYAML形式で記述されます。YAMLは、人間が読み書きしやすいデータ形式で、主に設定ファイルに使われます。基本的なルールは以下の通りです。
- インデント: スペースを使ってインデント(字下げ)を行います。タブは使用できません。通常、2スペースまたは4スペースでインデントします。
-
キーと値:
キー: 値
の形式でデータを記述します。キーと値の間にはスペースが必要です。 -
リスト:
-
(ハイフンとスペース)を使ってリストの要素を表現します。 -
コメント:
#
(ハッシュ記号)から始まる行はコメントとして扱われ、無視されます。
これらのルールを守って記述することで、pre-commit
が正しく設定ファイルを読み込むことができます。
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace # 行末の不要な空白を自動削除
- id: end-of-file-fixer # ファイル末尾に改行がない場合、自動で追加
- id: check-yaml # YAMLファイルの構文チェック
- id: check-added-large-files # 追加された大きなファイルがないかチェック
- repo: https://github.com/psf/black
rev: 24.4.0
hooks:
- id: black
files: \.py$ # Pythonファイルのみを対象
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
hooks:
- id: flake8
files: \.py$ # Pythonファイルのみを対象
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0
hooks:
- id: mypy
args: [--no-strict-optional, --ignore-missing-imports]
files: \.py$ # Pythonファイルのみを対象
各ツールの説明
-
pre-commit-hooks
:
pre-commit
が公式に提供している汎用的なフック集です。-
trailing-whitespace
: コードの行末にある不要な空白を自動的に削除します。 -
end-of-file-fixer
: ファイルの末尾に改行がない場合に、自動で追加します。Gitがファイルの変更を正しく認識するために重要です。 -
check-yaml
: YAMLファイルの構文が正しいかチェックします。 -
check-added-large-files
: コミットしようとしているファイルの中に、意図せず大きなファイル(例: バイナリファイル)が含まれていないかチェックします。
-
-
black
:
Pythonコードを自動で整形(フォーマット)するツールです。black
を使うことで、チーム内でコードの見た目を統一し、可読性を高めることができます。-
files: \.py$
: この設定により、.py
で終わるPythonファイルのみがblack
の対象となります。
-
-
flake8
:
Pythonコードのスタイルガイド(PEP 8)からの逸脱や、潜在的なバグをチェックする静的解析ツールです。コードの品質を向上させるのに役立ちます。-
files: \.py$
: この設定により、.py
で終わるPythonファイルのみがflake8
の対象となります。
-
-
mypy
:
Pythonコードの型ヒント(Type Hinting)が正しく使われているかをチェックする静的型チェッカーです。型エラーを早期に発見し、コードの信頼性を高めます。-
args: [--no-strict-optional, --ignore-missing-imports]
:mypy
の実行時に渡す引数です。プロジェクトの状況に合わせて調整してください。 -
files: \.py$
: この設定により、.py
で終わるPythonファイルのみがmypy
の対象となります。
-
ステップ3: pre-commit
フックのインストール
設定ファイルを準備したら、以下のコマンドを実行して、Gitリポジトリにpre-commit
フックをインストールします。
pre-commit install
このコマンドを実行すると、.git/hooks/pre-commit
というファイルが作成され、コミット時にpre-commit
が自動で実行されるようになります。
トラブルシューティング
コミットが失敗した場合
pre-commit
フックが失敗した場合、コミットは中断され、エラーメッセージが表示されます。
-
files were modified by this hook
と表示された場合:
これは、trailing-whitespace
やend-of-file-fixer
などのフックが、ファイルを自動的に修正したことを意味します。修正されたファイルはまだステージングされていないため、以下の手順で再度コミットを試みてください。-
git status
を実行して、修正されたファイルを確認します。 -
git add <修正されたファイル名>
(またはgit add .
)を実行して、修正をステージングします。 - 再度
git commit
を実行します。
-
-
black
、flake8
、mypy
などのフックが失敗した場合:
これは、コードにスタイル違反や型エラー、潜在的なバグなどが存在することを示しています。表示されたエラーメッセージを参考に、コードを修正してください。修正後、再度git add
とgit commit
を実行します。
pre-commit
の環境初期化に時間がかかる場合
pre-commit
は、初めてフックを実行する際に、各ツールの実行環境を初期化します。これには時間がかかる場合がありますが、一度初期化が完了すれば、次回以降は高速に実行されます。
まとめ
pre-commit
を導入することで、Gitコミット時に自動でコードの品質チェックが行われるようになり、より堅牢で統一されたコードベースを維持できるようになります。最初は戸惑うかもしれませんが、慣れてしまえば開発効率を大きく向上させる強力なツールとなるでしょう。
Happy Coding!