中規模プロジェクトにおけるコミット/Pull Request運用ベストプラクティス
📝 はじめに
本記事では、数人規模(2〜6人程度)のPythonプロジェクトを前提に、 GitHubでの コミット粒度・コミットメッセージ・Pull Request(PR)のサイズと運用について、 レビューが破綻せず、履歴が資産として残るベストプラクティスをまとめます。
ここで扱うのは主に以下です。
- 1コミットの適切な粒度とは何か
- 1プルリクエストに含める変更量の考え方
- 複数ファイルを変更する場合のコミット設計
- コミットログを「将来読む人」のためにどう書くか
ブランチ運用と同様、理想論ではなく現実的に回る運用を重視します。
🧱 基本思想:Git履歴は「記録」ではなく「説明書」
🎯 Git履歴の役割
Gitの履歴は単なる作業ログではなく、
- なぜこの変更が入ったのか
- どの単位で意味が完結しているのか
- どこまで戻せば安全か
を後から理解するための説明書です。
数週間後の自分、数か月後の他人が読む前提で設計するのが重要です
🧩 1コミットの適切な粒度
✅ 原則:1コミット = 1つの意味的変更
1コミットは、以下の問いに Yes と答えられる単位が理想です。
- このコミットは「何をしたか」を一文で説明できるか?
- このコミット単体で履歴に残っても意味が通じるか?
良い例
- 「CSVエクスポート機能を追加」
- 「起動時にNone参照で落ちる不具合を修正」
悪い例
- 「いろいろ修正」
- 「WIP」
- 「とりあえず動くようにした」
1コミット = 1ファイルではありません。「意味の単位」が基準です
📂 複数ファイルを含むコミットは問題ない
以下は同一コミットに含めるべき典型例です。
- 実装コード + それに対応するテスト
- モデル変更 + それに伴うバリデーション修正
- API変更 + 呼び出し側の修正
「この変更がなければテストが壊れる」なら、同一コミットが正解です
✂️ コミットを分けるべきケース
❌ 意味が異なる変更を混ぜない
以下は必ず分けるべきです。
- フォーマット修正 + ロジック変更
- リファクタリング + 挙動変更
- 不具合修正 + 無関係なついで修正
フォーマット変更を混ぜると、レビューも差分追跡も崩壊します
🧹 フォーマット・lint系の扱い
- 原則:専用コミットに分離
- 可能なら:専用PR
black / isort / ruff などは、履歴を壊しやすい代表例です
📝 コミットメッセージの書き方
📐 基本フォーマット(推奨)
<動詞(原形)>: <変更内容を簡潔に>
例
add: export results as CSVfix: prevent crash when config is missingrefactor: simplify validation logic
「このコミットは何をした?」に即答できるメッセージが理想です
📄 本文(必要な場合のみ)
以下の場合は本文を書く価値があります。
- なぜこの実装にしたのか
- 代替案を取らなかった理由
- 仕様上の注意点
How より Why を書くと、履歴の価値が上がります
🔀 Pull Request の適切なサイズ
✅ 原則:レビュー可能なサイズに抑える
目安として:
- 差分:数十〜300行程度
- 変更内容:1テーマ
「5〜10分で全体を理解できるか」が現実的な判断基準です
❌ 大きすぎるPRの問題点
- レビューが形骸化する
- 不具合が紛れ込む
- マージが遅れ、衝突が増える
レビューされないPRは、レビューがないのと同じです
🧩 1 PR = 何コミット?
📌 推奨パターン
- 作業中:複数コミット OK
- マージ時:Squash and merge
PR内では履歴の試行錯誤を許容し、main/develop には意味単位だけを残します
🔄 例外
- コミット単位で意味が明確
- 後から個別に revert したい
この場合は squash しない判断もあり得ます。
重要なのは「一貫した方針」をチームで共有することです
🧪 テストとPR運用
🧑🔬 PRに含めるべきもの
- 実装
- 最低限のテスト(または理由の説明)
「テストは後で」は高確率で永遠に来ません
🧯 よくあるアンチパターン
❌ 巨大PRを一気に出す
レビュー不能なPRは、事実上の単独マージと同じです
❌ コミットログが作業メモ
GitはTODOリストではありません
❌ PRタイトルと中身が一致しない
後から検索できなくなります
✅ まとめ:守るべき最小限のルール
- 1コミット = 1つの意味
- 意味が違えばコミットを分ける
- PRはレビューできるサイズに抑える
- マージ履歴は「将来読む人」のために残す
この運用は、人数増加・CI強化・リリース自動化にもそのまま耐えます