メインコンテンツへスキップ

概要

プルリクエストとは、リポジトリへの変更を提案し、その変更についてレビューなどの共同作業を行うための仕組みです。変更はブランチを介して提案されます。適用する内容を含むheadブランチから、変更の適用先であるbaseブランチに向けてプルリクエストを作成し、承認された内容だけが取り込まれます。

コミットメッセージ

コミットメッセージは、コミットに含まれる変更内容を要約する説明です。書き方をチームの規約として統一すると、履歴のどのコミットが何を変更したのかを一定の形式で追跡できます。 規約にはConventional Commitsの形式が広く使われます。<型>: <要約>の形式で、先頭に変更の種類を示すプレフィックスを付けます。 Conventional Commitsと合わせて、Semantic Versioningを使うことがあります。MAJOR.MINOR.PATCHの形式で、変更の互換性に応じて上げるバージョンレベルを決めます。ライブラリやAPIなど、互換性を管理する必要がある開発で利用することがあります。この2つを組み合わせると、コミットメッセージから変更内容を理解しやすくなり、リリースのバージョン番号を機械的に決定できるようになります。 組み合わせる場合は、<レベル>-<型>: <要約>のように型の前にバージョンレベルを付けます。破壊的変更を伴う機能追加はmajor-feat、互換性に影響しない小さな機能追加はpatch-featのように、型だけでは決まらないバージョンレベルを明示できます。 コミットメッセージは<型>: <要約>の1行だけでも成立します。変更の背景や理由を説明したい場合は、空行を挟んで本文やフッターを加えます。

タイトル

プルリクエストのタイトルは、変更内容を1行で要約する説明です。タイトルは一覧・通知・マージ後の履歴に表示されるため、本文を開かなくても変更内容を判別できる書き方に統一します。 タイトルはコミットメッセージをベースに、同じくConventional CommitsとSemantic Versioningの形式で決めます。コミットが1つのプルリクエストではそのコミットメッセージをそのまま使い、複数のコミットを含むプルリクエストでは変更全体を代表する型と要約を選びます。

テンプレート

プルリクエストの作成時に説明欄に自動挿入されるMarkdownのテンプレートを用意することができます。テンプレートがあると、概要・変更点・動作確認といった説明の構成がプルリクエストごとにばらつかず、レビュアーに渡すべき情報を事前にルール化できます。
1

テンプレートファイルを作成する

リポジトリに.github/PULL_REQUEST_TEMPLATE.mdを作成します。
2

雛形を書く

レビュアーが必要とする情報を、見出しとコメントで区切って並べます。
3

デフォルトブランチへマージする

テンプレートはデフォルトブランチに存在して初めて適用されます。マージ後に作成されるプルリクエストから、説明欄に雛形が自動で挿入されます。
テンプレートの内容は定期的に見直しましょう。誰も埋めていないセクションは削ります。レビューで質問することが多い項目などがあれば、セクションとして追加します。

Draft

Draftとは、レビューの準備が整っていないことを明示するプルリクエストの下書き状態です。Draft状態の間はマージがブロックされるため、作業途中の変更が誤って取り込まれることはありません。 未完成の段階でDraftとしてプルリクエストを開いておくと、実装や設計の方向性について、実コードの差分を見ながら早い段階でフィードバックを得られます。文書や口頭のすり合わせと違い、動くコードを前提に議論できるため、レビュアーと認識を早い段階で合わせられます。 必要なフィードバックが揃い、認識が合ったら、そのまま作業を継続しても、Draftのプルリクエストをcloseして新たにプルリクエストを作り直しても構いません。作業が進むほど方向転換のコストは膨らむため、早い段階で手戻りしてサンクコストを最小限に抑える手段としてDraftは有効です。 作成時に「Create draft pull request」を選択し、レビューを依頼できる状態になったら「Ready for review」でDraft状態を解除します。

粒度

プルリクエストの粒度とは、1つのプルリクエストが1つのことに注力できているかという、変更内容の一意性です。差分の行数やファイル数ではなく、変更内容が一意であるかどうかで測ります。

サイズと粒度の違い

サイズ(変更行数・ファイル数)と粒度(変更内容の一意性)は別の尺度であり、分割の判断に使うのは粒度です。判断基準は、差分が大きいかどうかではなく、プルリクエストの変更内容が一意である(1つのことに注力できている)かどうかです。

なぜ粒度が重要か

焦点の絞られた差分は、レビューする範囲も絞られます。作業量の合計が同じでも、10の変更を1つのプルリクエストでレビューするより、1の変更を10個のプルリクエストに分けてレビューする方が、作成者・レビュアー双方の負担が小さくなります。

レビューが速い

変更内容が一意な差分はレビュアーの頭に収まるため、レビューが後回しにされず、数分で終わります。

切り戻しが容易

変更内容が一意なプルリクエストをrevertすれば、その変更だけを巻き戻し、余計なものを巻き込みません。

conflictが減る

生存期間が短いブランチは、conflictが発生しにくくなります。

原因特定が速い

変更内容が一意なプルリクエストは影響範囲も絞られるため、障害時の切り分けが速くなります。
複数の変更内容が混在したプルリクエストは負の循環を生みます。レビュアーの認知負荷を上げ、レビューは後回しになり、ブランチは長く生き残り、conflictが積み上がって、次のレビューはさらに重くなります。 プルリクエストの粒度は、AIエージェントに作業させるときのコンテキスト管理の観点でも重要です。複数の要件や異なる内容を同じコンテキストで作業させると、焦点が分散して精度が落ちます。変更内容が一意なプルリクエストの粒度で作業させることで、コンテキストが1つのことに集中でき、実装・レビューともに精度が上がります。

粒度を適切にするコツ

先に作業を分解する

コードを書く前に独立して作業できるタスクへ分解し、各タスクが1つのプルリクエストに対応するようにします。詳細はタスク分解を参照してください。

迷ったら小さく分割する

適切な粒度に迷ったら、小さい粒度の方を選択します。レビューのやり取りの中で粒度について議論すれば、認識をレビュアーと揃えられます。 大きく作ったプルリクエストを後から分割するよりも、小さく作って後から粒度を大きくするほうが簡単です。迷ったときは小さく出し、段階的に肉付けしていきます。

レビューを最優先にする

粒度を小さくすると、マージしないと次の作業に着手できない場面が増えます。ここでレビューが滞るとボトルネックになり、開発スピード全体が低下します。そのため、レビュー依頼が来たら自分の作業より優先して対応します。 作業を中断するコンテキストスイッチが気になるかもしれませんが、粒度が適切なプルリクエストのレビューは数分、時には1分以内で終わるため、中断のコストはわずかです。粒度を適切に保つことが、レビューを最優先にする習慣がチームに根付く土台となります。

CIを高速に保つ

粒度を小さくするとプルリクエストの数が増え、それに比例してCIの実行回数も増えます。CIが遅いままだと、マージまでの待ち時間が積み重なって開発効率が逆に落ちます。 実行時間は10分切りが目安で、5分を超えたら遅いと判断して改善します。具体的な高速化の手法はCI/CDのCIを高速に保つを参照してください。

デプロイとリリースを分ける

コードを本番環境へ反映するデプロイと、機能をユーザーへ公開するリリースを別の出来事として扱うと、機能全体の完成を待たずに未完成の作業をマージできるため、プルリクエストを小さく出し続けられます。 詳細はリリースを参照してください。