- 大きな変更を小さくレビューしやすい階層に分割する Stacked pull requests が、すべてのリポジトリに公開プレビューとして順次提供される
- 各PRは直下の階層をターゲットにするため、チームメンバーは狭い範囲のdiffを並行して独立にレビューできる
- 最新のPRをマージすると、その下にある未マージの階層まで一度に反映され、一部だけをマージした場合は上位のPRが自動でリベースされ、ターゲットも変更される
- 既存のPRレビュー、必須チェック、ブランチ保護、マージ要件はそのまま適用され、GitHub.com・CLI・モバイルアプリ・GitHub Copilotでスタックを扱える
- 公開プレビューは数日かけて全リポジトリへ拡大され、Merge queue対応はその後数週間かけて段階的に提供される
小さな変更を積み重ねるPR構造
- 大きな変更を小さく焦点を絞った複数のPRに分け、各PRを順序のある変更階層として構成する
- 最初の変更用のブランチとPRを作成したあと、その上にブランチとPRを追加し、各PRは直下の階層をターゲットにする
- 単一の巨大なPRをレビューしたり、複数のブランチを手動で何度もリベースし続けたりする不便さを減らす
- Next.jsチームは、大きな機能をリリースしながらも個々の変更を小さく保てるため、PRレビューが容易になったと評価している
スタックの作成と作業環境
gh extension install github/gh-stack
- GitHub.com、GitHub CLI、GitHubモバイルアプリでスタックを作成・管理できる
- GitHub Copilotのようなコーディングエージェントでは、
gh-stack skillを利用できる
階層ごとの独立レビュー
- スタック内のPRを開くと、全体の変更ではなく、その階層のdiffだけをレビューできる
- PR上部のスタックマップで、現在の変更が全体の作業のどこに位置するかを確認できる
- チームメンバーが異なる階層を並行してレビューできるため、後続作業がレビュー完了までブロックされにくくなる
- 既存のブランチ保護ルールと階層別レビューを組み合わせて適用し、各段階の品質を管理する
- TEDは、AI導入で開発生産性が高まったあと、大きくなったPRがレビューのボトルネックにつながっていたとし、変更を依存関係の順序に沿って小さな論理単位に分けることで、レビューの速度と正確性を高めたと述べている
スタック全体または一部のマージ
- 準備が完了した最新のPRをマージすると、そのPRとその下にあるすべての未マージ階層を一度に反映する
- 下位階層の1つ以上だけを選んで、スタックの一部を先にマージすることもできる
- 上位のPRはオープンのまま維持される
- マージされた変更に合わせて自動でリベースされ、ターゲットブランチも変更される
- 既存のブランチ保護、必須チェック、マージ要件は引き続き適用され、
mainに入る変更を制御する
- スタック全体だけでなく、1つの階層または一部の階層だけを選択的にマージできる
公開プレビューと対応スケジュール
1件のコメント
Hacker News の意見
プレビューをしばらく使ってみたが、未解決の問題が多い状態で対象を拡大することに驚いている
たとえばスタック全体のマージは、さまざまな状況で完全に壊れる: https://github.com/github/gh-stack/discussions/212
1つずつマージすることはできるが、Squash merge と必須レビューを併用すると、スタック内の各 PR ごとに再承認を受ける必要があり、スタック型 PR の最大の利点が失われる
gh stackは手作業を少し減らしてくれるが、それでもgit rebaseを正確に理解している必要がある。ローカルブランチがリモートと同期していなければ、UI が案内するgh stack rebaseも失敗し、ツールはその原因を教えてくれない一方でスタック UI はシンプルでありながら PR 間の関係を十分に示してくれるので気に入っている。すでに PR を積み上げる理由があるという前提でワークフローを楽にするだけで、新しい機能を提供するツールではない
内部の CPRMC(Create Pull Request Merge Commit)は、コンフリクトの有無から承認内容が実際に作成されるコミットと一致しているかまでを検査し、PR のマージ準備状態を判断する
複数の PR を Squash merge するには、連続した squash コミットを計算したうえでルールやレビューに再び結び付ける必要がある。最初の PR は比較的簡単だが、2つ目以降は祖先コミットが squash されてブランチ上に元の形で存在しないため複雑になり、親が複数ある状況はさらに難しくなる
現在、スタックのマージは 99% が成功しているが、これを大幅に高めることがチームの最優先課題である
merging状態で止まり続けるバグに遭遇したPR システムの部分障害かと思って GitHub のステータスページまで確認したが、スタック型 PR 機能自体のバグだった
GitHub Stacked PRs チームで、誰でもスタックを作れるように、より広く公開した: https://gh.io/stacks
特に UI と CLI に関するフィードバックを求めており、PR の利用体験を改善するアップデートも多数準備中
Actions や保護ルールから CLI、モバイルアプリまで、ほぼすべてのサービスにまたがる GitHub 史上最大級のリリースの1つなので、設計上の判断や内部動作に関する質問にも答えられる
すでに独自のローカル UI でスタック型 PR の依存関係をツリーとして見て、各 PR のレビュー・CI 状態を管理しているので、GitHub の Web UI にもツリーと状態表示があるとよい
Web UI ではスタックの一番下の PR だけをマージする機能はサポートされていないようだが、既存のワークフローとコードを共有できるので、GitHub の標準ツールにも入ってほしい
公開リポジトリで有用にするには重要な機能に見えるので、公開プレビューより前に提供されなかったのは意外だった
コミット単位でレビュー・適用・修正できるきちんとした UI ではなく、この方式の元祖であるメーリングリストの パッチ束ワークフローを無視して、事実上「パッチ束の束」を選んだことに、何か別の洞察があったのか知りたい
ここ数年で GitHub に適用された変更の中でも指折りに大きい
世界最大級のコードホスティングプラットフォームの1つに スタック型ワークフローが導入されることで、多くの開発者が存在すら知らなかった方法に触れる可能性がある
スタックがより良いソフトウェアを作るという前提が正しいなら、実際に多くの開発者の助けになる可能性も大きい
よく整理されたコミットをコミットごとにレビューする方法と比べて、こうした スタック型 PR の利点が何なのか気になる
より大きな問題は、大規模な AI 生成 PR には別のレビュー方法が必要だということ。関数定義の変更、呼び出し側、テストの順に見せるように、差分の表示順だけでも読みやすさは大きく変わる
literate programming がコードと散文を結び付けるように、差分と説明を組み合わせた literate diff または literate PR が必要かもしれないが、まだ似たツールを見つけられていない
レビュー単位である PR または diff が1つの限定された変更として保たれるため、議論はその変更に集中し、機能が大きくなっても PR 自体は肥大化しない
また、スタックの各部分を別々の相手に任せることもできる。外部チーム、同じチームの同僚、その変更を使うチームのようにレビュアーを分ければ、各自が何を承認しているのかが曖昧にならない
GitHub のレビューが 変更 ID(change ID) を導入し、リベース後もコメントを維持できるようになるとさらによい
その後の PR をリベースして修正しなければならない点は、巨大な単一 PR の後続コミットを直すのと同じだが、変更全体に一時的な修正コミットをランダムに付ける代わりに、基盤となる変更のコミットをまとめて維持しやすくなる
基盤となる変更に関する議論もまとまり、スタック全体をあらかじめ提示すれば、レビュアーは最終的な方向性を把握しつつ、作業は非同期に進められる
コミットをゲームのセーブポイントのように使い、
fix bug、do workのようなメッセージだけを残してgit rebase -iで整理しないため、必須の Squash merge を有効にしていないとログがゴミコミットで埋まるこうした開発者にとっては PR がそのままコミットであり、スタック型 PR によって、1つの変更を構成する複数コミットに似た構造を初めて使えるようになる
マージ済みの diff は現在の HEAD の上にリベースでき、これをサポートするチームでは通常、ブランチを直接管理せず trunk で作業し、変更が入るたびにリベースする
機能の先頭 4つの部分が準備完了していて、5つ目に問題があるなら、全体を止める必要はない
依存関係のあるPRが線形履歴ではなくツリー構造になるケースは、いつサポートされるのか気になる
Googleでスタック型の変更を使っていたときはこうしたケースがよくあり、並列コーディングエージェントが増えた今ではさらに頻繁に起きそう
メニュー切り替えボタンがパンケーキの積み重ね絵文字(U+1F95E)なのは、スタック機能だからなのか気になる
遊び心のある表現自体はよいが、何を見ているのか強い疑念を抱かせるUIだった
数時間だけ表示したあと、通常のアイコンに戻す予定
最初にこのニュースを聞いたときから
gh stackCLIを使っており、ツール自体は非常に良かったが、プレビュー承認を受けて触ったWeb UIは期待を大きく下回った承認前でもCLIは作業を複数のアトミックなPRに分ける自動化を簡単にしてくれたが、プッシュすると互いに関連付けられていない独立したPRとして表示された
承認後もほとんど同じで、上部の小さなナビゲーション用ドロップダウンに同じスタック内の別PRが表示されるだけで、意味のあるUI変更がない
ドロップダウンからCLI機能の一部を実行できるが、Webでファイルを編集する機能のような副次的な便利機能に近く、実際の開発ワークフローではCLIやIDEプラグインが中心になるはず
この程度の任意UIのために、なぜ長い間一般公開を遅らせたのか疑問で、スタックCLIは発表時点からすでに一般公開状態だった
スタックを常に認識し、何度もクリックしなくても各階層を行き来できるよう、スタックを継続的に表示する画面も含める予定
jujutsuはブランチを更新すると、そのブランチから分岐した他のブランチも自動的にリベースしてくれる点が良い
レビューしやすいように作業を分けるときはよく
jjに切り替えており、Gitで作ったクローンと同じ作業ディレクトリで併用しても問題なく動くjj absorbも素晴らしい変更内容を最も近い関連変更へ移してくれるので、複数のPRに影響する修正も簡単に扱える
Graphiteを使った後は、スタックのないGitHubに戻るのが非常に難しかった
GitHubのサポートによってスタック型PRワークフローが一般化し、巨大なPRの代わりになる簡単な選択肢が生まれることを期待している
git-spiceをおすすめする使いやすく強力なオープンソースで、Graphiteは機能の割に過度に複雑に感じた
PRを積むことは2つの状況で有用だと理解していた
1つ目は、相互に関連する複数のリポジトリにまたがっていて1つのPRにまとめられない場合、2つ目は、最初のPRをレビューしている間に同じブランチ上へ後続PRを積んで作業をパイプライン化する場合
しかしこの機能はそのどちらも満たしておらず、単一のPRにコミットを積む別の形のように見える
一般的には、アトミックで意味のあるコミットを作り、リベースでレビュアーが理解しやすい流れを構成し、レビュアーも望めばコミットごとに確認できる
この方式で見落としている固有の利点が何なのか気になる