大規模なプルリクエストはレビューが難しく、特に AI が短時間で大量のコードを生成するのに役立つ場合、ボトルネックを生みます。 pull request サイズが大きくなると、レビューの品質も低下します。 レビュー担当者は、結果にざっと目を通し、問題を見落としたり、あるいは先延ばしにして、古くなってマージ競合が発生するまで pull request を放置したりすることがあります。
スタックされたプル リクエストでは、大きなコード変更をレビュー可能な状態に保ちます。
スタックは、同じリポジトリ内の一連のプル要求です。各プル要求は、その下のプル要求のブランチを対象とし、1 つのブランチ (通常はメイン ブランチ) に配置される順序付きチェーンを形成します。 1 つの大きなプル要求の代わりに、一連の小さなプル要求を取得します。 各プル要求には独自のフォーカスされた差分があるため、チームメイトは各レイヤーを個別に確認して承認できます。
このチュートリアルでは、エージェントと共にスタックされたプルリクエストを使用して、機能を個別にレビュー可能な層に分けて構築する方法について説明します。 この例では、アプリにユーザー認証を追加する方法を検討します。
GitHub Copilot CLIとgh-stack エージェント スキルを使用します。
前提条件
エージェントで gh-stack スキルを使用するには、まず、 GitHub CLI と gh-stack CLI 拡張機能をインストールする必要があります。 以下のものが必要です。
- GitHub CLI (
gh) 2.90.0 以降、および Git 2.20 以降。gh auth loginでGitHub CLIを認証します。
- プッシュできる GitHub リポジトリ。
- GitHub Copilot CLI インストールされ、サインインしています。
GitHub CLIで、gh-stack拡張機能とスキルをインストールします。
gh extension install github/gh-stack
gh skill install github/gh-stack
メモ
このチュートリアル全体を通して、Copilot に実行させるのではなく、自分でスタック コマンドを実行する場合は、GitHub CLI を使用する必要があります。
1. コードを生成する前にスタックを設計する
良いスタックは家を建てるようなものです。まず強い基盤から始めて、壁の骨組みを作り、配線を取り付け、それからドライウォールを仕上げます。 構築された各レイヤーは、その下のレイヤーに依存します。 最後に、レビュー担当者は、下から上にプルリクエストを読み取り、機能が形になっていく流れを追える必要があります。
- フィーチャをレイヤーに分割します。 各レイヤーは、単独で確認できる単一の一貫性のある変更である必要があります。
- 各レイヤーは、プルリクエストが簡単に読める程度に小さくします。 レイヤーのレビューに長い説明が必要だと感じる場合は、おそらく大きすぎる可能性があります。
- 自分で範囲を決めるか、Copilot と一緒にプランを立てます。 どちらの方法でも、スタック構成を自分で決められます。
- 依存関係別にレイヤーを並べ替える。 基本的な変更は下部にあります。 それらに依存するものは、上位に表示されます。 認証の場合、次のようになります。
- レイヤー1: データモデルと移行
- レイヤー 2: CRUD エンドポイント
- レイヤー 3: JWT ミドルウェアとガード
- レイヤー 4: 統合テストと単体テスト
プロンプトの例
Propose a layered approach to add user authentication to this app. Order the layers by dependency, keeping each layer independently reviewable.Review my planned layers and flag any that are too large or that depend on a branch above them.
2. 最初に下部レイヤーを構築する
基盤からスタックを開始します。 上記のすべては、このレイヤーを適切に設定できるかどうかにかかっています。
- Copilot に、スタックされたプルリクエストを作成することを伝え、プランに基づいて最初のレイヤーを構築するよう依頼します。 エージェントは、
gh-stackスキルを使用してスタックの最初のブランチを作成します。 - スタックを自分で作成する場合は、
gh stack initで直接作成し、プレフィックスを使用してブランチ名を整理します (例:gh stack init BRANCH-NAME-1)。 - 次に進む前に、生成された変更を自分で確認してください。 下位レイヤーの間違いは、その上のすべてのブランチに反映されるため、次に進む前にレビューを行ってください。
プロンプトの例
Start the pr-stack and build only the first layer: the user data model and migration.Conduct a review of the generated code and confirm this branch contains only the data model and migration, and nothing that belongs in a later layer.
3. 新しいコード レイヤーをそれぞれ上に積み重ねる
基盤を整えた状態で、フィーチャの残りの部分を 1 レイヤーずつ構築します。
- Copilotに次のレイヤーを追加し、以下のレイヤーのコンテキストで実装するように依頼します。 エージェントは、スタックの一番上にブランチを追加し、そこで作業をコミットします。
- ブランチを自分で追加する場合は、
gh stack add BRANCH-NAME-NEXTを使用します。 - レイヤーが大きくなりすぎる場合は、当初の設計から逸れていないか、あるいは 1 つではなく 2 つのレイヤーが実際に必要かどうかを検討します。
- レイヤーごとに新しいブランチを作成し、すべてのブランチがクリーンで自己完結型の差分を維持するようにします。
- プル リクエストを作成する準備ができたら、スタックの送信を Copilot に要求するか、自分で実行する場合は、
gh stack submitを使用します。 - 各プルリクエストはそれ単体で完結させてください。 通常は、重点を置いたタイトルと、レイヤーの簡潔でわかりやすい説明で十分です。
プロンプトの例
Add the next layer in a new branch on top: the CRUD endpoints that use the user model from the branch below.This branch is getting large. Suggest how it could be split into two independently reviewable layers.
4. レビューを依頼する前に pull request を自分で確認する
各レイヤーは小さく、自己レビューも簡単になります。 チームメイトを巻き込む前に、各ブランチを一通り確認してからにします。 レビュー担当者は、あなたが既に信頼している変更を受け取る必要があります。
- 各ブランチでテスト、リンター、コードスキャンを実行してください。 レビューを依頼する前に、Copilot が各レイヤーを標準に照らして確認するのを支援します。
- AI によって生成された変更を徹底的に確認する手法については、 AI によって生成されたコードを確認する を参照してください。
5. スタックのレビューを一番下から要求する
レイヤーを構築すると、校閲者はコードの大きな壁ではなく、小さな差分を取得します。
- 依存関係が強く結び付いている場合は、スタックの下部からレビューを依頼して、後続のレビューの前に変更をスタックの上位へ反映できるようにします。
- 異なるレイヤーごとに別々の担当者からのレビューが必要な場合は、レビュー担当者が並行して作業できます。 1 人のユーザーがデータ モデルを確認し、別のユーザーがエンドポイントをレビューし、どちらも機能全体に目を通す必要はありません。
6. フィードバックを基に改善を重ねる
フィードバックは、機能全体ではなく、レイヤーに個別に反映されます。 スタックを使用すると、適切なレイヤーを所定の位置に固定し、変更を上位へ反映できます。
- レビュー担当者がフラグを設定したレイヤーを修正するように Copilot に依頼します。 エージェントは右ブランチに移動し、変更を行い、そこでコミットします。 次に、上のレイヤーをリベースして修正を取り込めるようにします。
- 各修正は、それが属するレイヤーに残してください。 間違ったブランチで行われた変更により、混乱を招き、上流工程でエラーを引き起こす可能性があります。
- 修正を行う際は、上記のブランチをリベースし、変更を反映するように Copilot に依頼してください。
- スタック内を自分で移動する場合は、
gh stack down、gh stack up、またはgh stack checkout BRANCH-NAMEを使用してブランチをたどります。 次に、変更をコミットし、gh stack rebase --upstackを実行して変更をスタック上位へ繰り上げます。
プロンプトの例
A reviewer flagged that the auth service doesn't handle expired tokens. Fix that on BRANCH-NAME and test the changes.I've rebased the layers above onto this fix. Check that the branch with endpoints still works with the change and flag anything that needs updating.
7. 下のレイヤーから結合する
スタックは、メイン ブランチを指すレイヤーから順にマージされます。 レイヤーを一度に、または1つずつマージし、GitHubは自動的に次のレイヤーのターゲットを main に変更します。
- スタックを一度に 1 つずつ下から順にマージするか、またはスタック内の任意の場所からマージすると、マージするプル要求の下にあるすべてのブランチが一番下からマージされます。
- 各レイヤーの差分は親に対してまったく同じままで、変わるのはベースだけであるため、進行中の作業やレビューに影響を与えることなく、レイヤーを1つずつ簡単にマージできます。
- 自動マージまたはマージ キューを使用して、各レイヤーが承認され、そのチェックが成功するとすぐにマージされるようにします。 スタック全体が完了するのを一度に待つ必要はありません。
最上位レイヤーがマージされると、フィーチャ全体が反映されます。 すべての部分は、1 つの大きなプルリクエストではなく、小さな意図的な変更としてより効果的にレビューされました。