世界を動かす技術を、日本語で。

GitHubのスタックされたプルリクエスト

概要

  • 大規模な変更 を小さな レビュー可能なPull Request(PR) に分割するメリット
  • GitHubの ネイティブサポートgh stack CLI の活用方法
  • Stacked PR の管理・レビュー・マージの流れ
  • CLIコマンド例 と導入手順の簡単なガイド
  • AIエージェント連携 による開発効率化

Stacked Pull Requestの基本とメリット

  • 大規模な変更 は小さく焦点を絞ったPRに分割し、 順序立ててレビュー する運用
  • 各PRは 独立したレイヤー として扱い、 個別にレビュー・承認 可能
  • GitHub UI 上でスタック全体を一目で把握でき、 ワンクリックで全体マージ も対応
  • gh stack CLI によるローカルでのスタック作成・管理・リベース・PR作成の自動化
  • AIエージェント (例:npx skills add github/gh-stack)との連携による自動化支援

Stacked PRの運用フロー

  • スタックは 同一リポジトリ内の一連のPR で構成し、各PRは 下位のPRのブランチ をターゲットにする
  • 最終的に mainブランチ 等のターゲットブランチに連なる 順序付けられたチェーン を形成
  • GitHubは 全レイヤーのスタックマップ を表示し、 ブランチ保護ルールやCI も最終ターゲットブランチ基準で適用
  • gh stack CLI でブランチ生成・リベース・GitHubへのプッシュ・PR作成を一括管理
  • マージ時は スタック全体または一部を一括マージ し、残りのPRは 自動リベース される

gh stack CLIの導入と基本コマンド

  • CLI拡張のインストール
    • gh extension install github/gh-stack
  • コマンド短縮エイリアス (任意)
    • gh stack alias
  • スタックの初期化
    • gs init auth-layer
  • 新しいレイヤーの追加
    • gs add api-routes
    • gs add frontend
  • 全ブランチのプッシュ
    • gs push
  • スタックPRの作成
    • gs submit

Stacked PRの利点と現場課題の解決

  • 大規模PRの問題点
    • レビュー困難、マージ遅延、コンフリクト頻発、レビューアの文脈喪失、フィードバック品質低下、チーム全体の開発速度低下
  • Stacked PR導入による解決策
    • 変更点ごとに 小さく焦点を絞ったPR を積み重ね、 独立レビュー迅速なマージ を実現
    • 開発初期からスタック運用 することで、 大規模diffの分割段階的な開発 が容易

スタック管理の実践ポイント

  • GitHub UI でレイヤー間ナビゲーションとスタックマップ確認
  • CIや保護ルール が最終ターゲットブランチ基準で自動適用
  • マージキュー直接マージ の選択肢
  • マージ後の自動リベース による後続PRの整合性維持

導入ガイドと次のステップ

  • Quick Startガイド詳細なドキュメント で運用開始をサポート

  • AIエージェント連携 でさらなる自動化・効率化推進

    • 開発現場の コードレビュープロセス最適化
    • チーム開発の生産性向上

Hackerたちの意見

やっとだ!GitHubがデフォルトで使ってるPR=ブランチモデルがずっと理解できなかったんだ。スタックコミット(Phabricator/Gerritみたいなやつ)の方が、変更について考えるときに頭に合ってる。こういうオプションが出てきて嬉しいな。これからCLIもインストールしなきゃね。

最初に気になるのは、GH CLIに頼らなきゃいけないところかな。俺も使ってないし。でも、GAになる頃にはUIサポートが追加されてるかもね。

PhabricatorとMercurialを使ってた者として、GitHubとGitを再び使うのは石器時代に戻る感じがする。これと呪術があれば、Phabricatorのスタック差分フローを再現できるといいな。モノレポだけじゃなくて、長期的な機能プロジェクトのレビューや作業がずっと楽になるんだよね。小さなPRや差分を促進するから、ビルドの合間にサクッとレビューできるし(長いプルリクエストは時間がかかるから)。

GitHubのレビューが耐えられないから、Gerritを使い続けてるよ。理論上は、変更を小さくするべきなんだけど、大きな作業(ベンダー依存関係の更新とか)をやってると、GitHubでファイルをレビューするのは…あんまり良くないね。

Gitがdvcs戦争に勝ったことが本当に嬉しい。Mercurialが「Gitより速い」ってずっと宣伝してた時代があったけど、試してみるたびにいつも遅いか壊れてた(時々)。Gitは見た目はイマイチだけど、速くて信頼できるし、これでやっていける。

PhabricatorのレビューUIが恋しいなぁ。

ソロ開発者としてはスタックPRはあまり必要ないけど、PRを小さくてレビューしやすく保つっていう根本的な問題は、たとえ自分がレビューしてもリアルだよね。作業を始める前に小さなブランチに分けるように自分を強制するのが、実際のディシプリンだと思う。そうしないときの苦痛を和らげるのがツールなんだよね。AI支援のワークフローに何か変化があるか気になるな。今はClaude Codeに機能ブランチで作業させてるけど、自然に一つの大きな差分ができちゃう。エージェントが自分の作業を論理的な塊に分けられるようになれば、スタックPRは面白くなるかも。

ウェブページにアクセスすると、エージェントの統合手順が表示されるよ。

そのためのツールはすでに存在してるよ。PRは複数のGitコミットで構成できて、UIで別々に見ることもできる。エージェントがそれをうまくナビゲートできるかは分からないけど、できないならスタックPRでもあまり変わらないと思う。スタックPRはレビュー過程に新しい利点を生むけど、君が求めてるものとは違う気がするな。

もしかしたら知らないGitのトリックがあるかもしれないけど、互いに小さなブランチを作るのが辛いと感じてる。以前のブランチを更新すると、依存してるブランチが同期しなくなって困るんだ。以前のブランチがマスターにリベースされると、進行中のブランチを更新するのが面倒になるよ。

Claudeとjjを使って、やった作業のスタックを元に、レビューしやすい新しいスタックを作るっていうのがうまくいってるんだ。

何か見落としてるかもしれないけど、俺が必要なのは「スタックされたPR」じゃなくて、単一のコミットを管理するためのちゃんとしたUIとインターフェースなんだよね。具体的には、 - 一部の作業が準備できたら、独立してコミットをマージしたい。 - いくつかのコミットをレビュー済みとしてマークしたい。 - インタラクティブリベースやスカッシュ、個別のコミットを編集するためのUIがほしい。 (コマンドラインではうまくできるけど、GitHubのインターフェースだと難しいし、チームの全員がそれに慣れてるわけじゃない) - 特定のコミットやコミットメッセージにコメントを付ける機能。 - 各強制プッシュ/リビジョンでの変更を視覚化するためのより良い方法(diff of diff)。 Git自体はコミットの概念を持ってるのに、なんでこの「スタックされたPR」って抽象化を上に乗せるの?それとも、俺が見えてない違いがあるの?

基本的には、Phabricatorが開拓したスタック差分ワークフローをGitHubに持ち込もうとしてるんだ。これによって、まだマージされてないものの上で作業するのがうまく扱えるようになって、レビューアが大きな作業の一部を独立してレビューしやすくなる。大きな企業環境では本当に役立つよ。モノレポでreact-nativeをアップグレードする時にスタックされたPRを使ったことがあるけど、大量の変更が必要で、一つのプルリクエストとしてレビューするのは本当に大変だった。一度に全部マージしなきゃいけないから、全か無かなんだ。でも、小さな独立したPRとしてレビューできるのは助かる。スタックされたPRは、全部を一度にマージする必要がない時でも役立つよ。

ワークフローは様々だけど、俺が好きなのは:PR/MRは「原子的」な変更(理想的には別々にマージできる最小の変更 - 最小だとレビューやバイセクト、リバートがしやすい)で、個々のコミット(Phabricatorでいう「バージョン」)はその変更を達成するためのPR/MRの進化に使われる。実際には、コミットには2つの使い道があるんだ:1. PR/MRがまだ大きすぎるから、個々のコミットに分ける(一緒にマージされるのは分かってる) 2. コミットの中にPR/MRの進化の履歴を残す(「fooをbarに変えたのは、より良いアプローチだから」)。

Gitの履歴を常に書き換えるのって、スカッシュやリベース、手動変更、強制プッシュを使ってると、足元に向けて銃を向けてるみたいに感じるんだよね。特に、普通の意識の流れでのコミットやブランチマージでも同じメリットが得られるし、こういうコマンド使えばいいんだよね:git merge --no-ff、git log --first-parent、git bisect --first-parent。

スタックされたPRに特化したスタートアップ、Graphiteっていうのがあるんだ。しばらく使ってるけど、なんでGitHubが似たようなものを実装しないのかいつも不思議に思ってる。多分、GitHubに切り替えて、ちゃんと動くか試してみるつもり。

うん、仕事でグラファイト使っててめっちゃ満足してる。

現在のUXの問題をSquash & Mergeで解決できるのかな?今は手動で「スタックされたPR」をこんな感じでやってるんだ:main <- PR A <- PR B(PR Bのマージ対象ブランチはPR A)<- PR C、みたいに。もしPR Bが先にマージされたら、PR Aは問題なくmainにマージできる。けど、PR Aが先にmainにマージされたら、PR Bを直すのが悪夢だ。GitHubのUIは自動的にPRの「ターゲット」ブランチをmainに変えちゃうけど、すぐにどこからともなくコンフリクトが発生する。リベースしようとすると、そのブランチで起きたすべての非コンフリクトの変更を手動で見なきゃいけなくなる、理由もなく(そう、理由はPR Aがmainにマージされたことで新しいマージコミットができて、Gitがそれをうまく扱えないから)。だから、これに新しいUIは本当に必要ないんだ。1998年にLinusがリベースの教えを我々に授けた時に、彼じゃない人にも分かるように、ツールがちゃんと動くことが必要なんだ。

コンフリクトが発生するのは、PR Aがスカッシュされたからで、スカッシュするとGitはPR Bの祖先コミットがmainのスカッシュされたコミットと同じだって分からなくなるんだ。この機能がこれを修正するかは分からない。編集:gh stack syncが正しくリベースしてくれることを願ってる(PR Aの最後のコミットをベースにしたリベース --onto)。

もし私が正しく理解しているなら、コンフリクトはすでにmainに加えられた他のコミットから生じているんだよね。つまり、ブランチAをmainに追いつかせたから、今度はブランチBをmainに追いつかせる必要があるってこと。クリーンにマージするためにはこれ以外の方法はないと思うんだけど、これはgitの問題じゃなくて論理的な問題だよね?

GitHubのスタックPRチームからこんにちは!プライベートプレビュー中で、今後数週間で待機リストの方々に展開していく予定です。https://gh.io/stacksbeta 仕様やCLI、ワークフローについてのフィードバックをお待ちしてます!

これがGHEにいつ来るか、何か情報ある?リリースサイクルは全然違うのは知ってるけど、あなたの考えが気になる。

小さくて焦点を絞ったプルリクエストの連鎖で、それぞれが独立してレビュー可能。 これが何を意味するのか、全然理解できない。変更が直交しているなら(独立してマージできる)、それぞれが自分のPRになるはずだし、そうでないなら、なんで独立してレビューしたいの?変更Aを却下して変更Bを承認したら、何もマージできないよ。だってBはAが必要だから。変更Aを承認して変更Bを却下したら、機能は半分しか完成してない。結局、他の変更に気を取られないように論理的な塊を分けたいだけなのかな?それなら、PRをコミットに分けて、一つずつ見てもらうだけでできることじゃない?スタックディフの支持者に好意的に考えようとしたけど、全然意味がわからない。

ここでの典型的な例は、バックエンドとフロントエンドの両方の作業が必要なウェブサイトの機能だよね。フロントエンドはバックエンドに依存してるけど、バックエンドはフロントエンドに依存してない。つまり、最初のコミットは「独立」していて、二つ目なしでもマージできるけど、二つ目はそうじゃないからスタックになる。スタックの根元は、上に何があっても独立してマージできるけど、他の部分は依存してる。 > そうでないなら、なんで独立してレビューしたいの?この例では、バックエンドエンジニアとフロントエンドエンジニアの両方からレビューを受けたいかもしれない。でも、これも見てほしい: > PRをコミットに分けて、一つずつ見てもらうだけでできることじゃない?PR内でこれをやると、二人とも全体をレビューすることになる。各人は、自分が気にしないコードも見ることになるから、グループ化されちゃう。通知も、各セクションを気にする人ではなく、全員に行く。両方のレビューは独立して進められる。 > 変更Aを承認して変更Bを却下したら、機能は半分しか完成してない。これは「機能」が何を意味するかによるよね。一つの大きな機能として見れば、確かに両方がマージされるまで完成とは言えない。でも、二つの関連するけど別々の機能として見れば、独立した変更を依存するものの前にマージするのは全然問題ない。片方の機能は完成してるけど、もう片方はまだ。

「変更Aを拒否して変更Bを承認すると、何もマージできない。今回のケースでは機能も半分しかできてない。著者はAでレビュワーが持っていた懸念を修正して、両方を同時にマージできるようにすればいい。」

スタックPRの意味が全然わからない。普通にgitを使えば、一連のパッチを送って、個別にレビュー、テスト、適用できるのに。PRのワークフローでは、パッチのシリーズが一つの変更セットになって、まとめてレビュー、テスト、適用しなきゃいけなくなる。スタックPRはこの問題を回避しようとしてるけど、そもそもPRの実装に問題があるんだよね。本当に求めてるのは、個別のコミットやパッチを再度レビューできる能力であって、一度に全体のバンドルを扱うことじゃない。スタックPRは、最初の抽象化の問題を回避するための第二層の抽象化のように見える。

多くの組織で見られる間違いの一つは、時々、順序がどれだけ重要かを考えすぎることだよね。確かに、アプリケーションはそのデータベースに依存してるけど、だからといってデータベースができる前にアプリケーションをデプロイできないわけじゃない。データベースがオンラインになるまで、アプリケーションがクラッシュループに入っても許容できるようにすればいいんだよ。