pr-stack について
積み重ねたブランチとプルリクエストを管理するスキルです。リポジトリで設定済みの Graphite、git-town、GitHub gh stack を検出し、通常の Git で代用せず、作成、同期、提出、競合回復を案内します。
主な機能
- 01設定済みのスタックツールを検出
- 02ブランチスタックの作成と確認
- 03スタックしたプルリクエストの同期と提出
- 04ツール固有コマンドで競合を回復
- 053つのツールのワークフローを比較
活用シーン
- 01依存するプルリクエストの連鎖を管理
- 02trunk の変更後にブランチを再配置
- 03スタック全体を提出または更新
- 04スタックのリベース競合から復旧
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ paulnsorensen/ skillz-that-grillz --skill pr-stackインストール後、Claude Code で/pr-stackを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/gh-stack.mdgit-town.mdgt.md詳細
pr-stack
スタックブランチ:各ブランチで1つのPRを作成する小さなブランチを連ね、リベース後も順序を保ったまま、まとめてプッシュします。
現在、このワークフローを実現するツールは3つあります。いずれも同じ考え方に基づいていますが、それぞれ異なるエコシステムで提供されています。
- Graphite(
gt) — サードパーティ製の成熟したCLIです。Graphiteアカウント(gt auth)が必要です。スタックのメタデータは.git/.graphite_repo_configに保存されます。 - git-town(
git town) — サードパーティ製の成熟したCLIです。アカウントは不要で、特定のフォージに依存しません(GitHub/GitLab/Gitea/Bitbucket/Forgejo/Azure DevOps)。ブランチの系譜はローカルのgit設定(git-town-branch.<name>.parent)に保存されるため、登録は不要です。 - GitHub
gh stack— GitHub公式のgh拡張機能(github/gh-stack)です。2026-05時点ではプライベートプレビュー中です。リポジトリはgh.io/stacksbetaから許可リストに登録する必要があります。スタックのメタデータは.git/gh-stackに保存されます。標準のgh auth loginを使うため、サードパーティのアカウントは不要です。
このスキルは、ユーザーが利用しているツールを選び、そのツールでワークフローを実行します。通常のgitでスタックを再現することはありません。
検出 — 何よりも先に実行する
# gt available?
command -v gt >/dev/null 2>&1 && gt --version >/dev/null 2>&1
# gt initialized in this repo?
test -f "$(git rev-parse --git-dir)/.graphite_repo_config"
# gh stack extension installed?
# (gh extension list output is TAB-separated: <short-name>\t<owner/repo>\t<version>)
# Guard with `command -v gh` so the probe stays quiet when gh itself is missing
# — `2>/dev/null` on the pipeline doesn't catch the shell's own "command not
# found" message.
command -v gh >/dev/null 2>&1 \
&& gh extension list 2>/dev/null | awk -F '\t' '$2 == "github/gh-stack"' | grep -q .
# git-town available?
command -v git-town >/dev/null 2>&1 && git town --version >/dev/null 2>&1
# git-town configured for this repo? (non-empty trunk = set up)
git config --local --get git-town.main-branch >/dev/null 2>&1
リポジトリがすでに設定されているツールを選びます。 ここでツールを利用可能とみなすのは、インストールされており、かつこのリポジトリ向けに設定されている場合です。
| ツール | インストール済みかの確認 | リポジトリ向けに設定済みかの確認 |
|---|---|---|
gt | command -v gt | .git/.graphite_repo_configが存在する |
git town | command -v git-town | git config --local --get git-town.main-branchが空でない |
gh stack | gh extension listにgithub/gh-stackが含まれている | 事前確認なし — リモート操作が終了コード4で終了した場合に遅延検出 |
次のように対応します。
- 利用可能なツールが1つだけ → そのツールを使い、対応するリファレンスを読みます。
- 利用可能なツールが複数ある →
gt(GAで成熟しており、リポジトリですでにスタックを追跡している可能性があります)、次に**git town(GAでアカウント不要、フォージ非依存)、次にgh stack**(GitHub公式ですが、プライベートプレビュー中)の順に優先します。他にインストールされているツールをユーザーに伝え、切り替えるか確認します。 - インストール済みだが未設定 → 初回セットアップ(
gt init、またはgit config --local git-town.main-branch <trunk>— trunkの名前を指定します。例:main/master。gh stackではリポジトリの初期化は不要)を提案し、そのまま続行します。 - 利用可能なツールがない → 停止します。
git pushを連ねて代用しないでください。下の「未インストールの場合」を参照してください。
毎回の実行時に確認コマンドを実行してください。セッション間でユーザーの環境が変わる可能性があります。
インストール済みのツールがない場合
検出時に gt、git town、gh stack 拡張機能のいずれも見つからない場合は、以下をそのまま表示して終了します。
このマシンまたはリポジトリでは、スタック型 PR ツールを利用できません。次のいずれかをインストールしてください。
- Graphite CLI —
brew install withgraphite/tap/graphite(またはnpm install -g @withgraphite/graphite-cli@stable)を実行し、その後gt auth --token <https://app.graphite.com/activate から取得したトークン>を実行してから、 このリポジトリ内でgt initを実行します。- git-town —
brew install git-town(Windows ではchocoまたはscoop)を実行し、その後 このリポジトリ内でgit config --local git-town.main-branch <trunk>(trunk の名前。例:main/master。またはgit town config setupウィザード)を実行します。さらに、git config --local git-town.github-connector gh(既存のgh認証を再利用)またはgit-town.github-tokenPAT のいずれかを設定します。GitHub、GitLab、Gitea などで動作します。- GitHub ネイティブの
gh stack—gh extension install github/gh-stackを実行し、 リポジトリが gh.io/stacksbeta の許可リストに登録されていることを確認します(2026-05 時点でプライベートプレビュー)。いずれかをインストールしたら、
/pr-stackを再度呼び出してください。こちらで進めます。
通常の git push の連続実行や、親ブランチの手動設定、PR の手動リンクで代用しないでください。このスキルの価値はスタック対応の仕組みにあり、それを装うと、ツールがないことをユーザーに伝えるよりも悪い結果になります。
3 つ目の失敗モード — gh stack はインストール済みだが、リポジトリが許可リストに登録されていない場合。
CLI はどこにでもインストールできますが、リポジトリがプライベートプレビューの許可リストに登録されていない場合、リモート操作(submit、sync、link)は終了コード 4 で失敗します。終了コード 4 が確認された場合は、その旨を表示し、ユーザーに gh.io/stacksbeta を案内してください。ローカルに gt もインストールされている場合は、このリポジトリでそちらに切り替えることを提案してください。
メンタルモデル(共通)
- トランクは
main(またはリポジトリで使われている名前)です。 - スタックはブランチの連なりで、それぞれのブランチは 1 つ前のブランチを親とします。すべてのスタックの最下部はトランクです。
- ブランチごとに PR が 1 つあり、それぞれの PR は親ブランチを対象とします。レビューは下から上へ進みます。
- Submit はチェーン全体をプッシュし、ブランチごとに PR を 1 つ開くか更新します。
- Sync はトランクを取り込み、残っている各ブランチを新しいトランクの先端に積み直し、PR がマージ済みのブランチを削除します。
3 つのツールはすべてこのモデルを実装しています。コマンド名は異なります。ツールごとのリファレンスを参照してください。
スタック内の PR がマージされた後
一番下の PR(またはスタック内の任意の PR)がマージされたら、残りのスタックを新しい trunk に追従させ、マージ済みのブランチをスタックから外す必要があります。これは通常の「sync」のタイミングとは別の重要なタイミングです。通常の同期サイクルで取り上げられるまで待たないでください。
ツールの同期コマンドを実行します。
| ツール | コマンド | 動作 |
|---|---|---|
gt | gt sync then gt submit --stack | trunk をフェッチし、残りのブランチをローカルで新しい trunk の先端にリスタックしてから、マージ済み/クローズ済みのブランチを削除するか確認します。その後、submit によりリベース済みの残りのブランチをプッシュします。 |
gh stack | gh stack sync (gh stack submit only if you have unpushed local commits) | GitHub はマージ時にすでにサーバー側でリベースをカスケードしているため、同期では主にその状態をローカルに反映し、ローカル参照を更新します。 |
git town | git town sync --stack | trunk をフェッチし、マージ済みのブランチを外して、残りのブランチをローカルで新しい trunk の先端にリベースし、フォージがそれらの PR のターゲットを変更するように強制プッシュします。 |
重要な違いは、gh stack では一番下の PR がマージされた時点で、GitHub サーバーが残りのブランチをすでにリベースしていることです。そのため、あなたの作業はその状態をローカルに反映することであり、リベースを再計算することではありません。gt ではリベースがローカルで行われるため、gt sync がマシン上で実際の処理を行います。
同期中にコンフリクトが発生した場合(trunk と残りのブランチが同じ行を変更している場合)、ツールのコンフリクト復旧フロー(gt continue / gt abort、git town continue / git town skip、または gh stack rebase --continue / --abort)に移ってください。単独の git rebase --continue は絶対に使わないでください。ツールのメタデータが更新されません。
同期が成功したら、次の submit の前に gt log short / git town branch / gh stack view を実行し、ブランチの連鎖が正しいことを確認してください。
ツール対応表
| 操作 | gt | git town | gh stack |
|---|---|---|---|
| スタックのメタデータを初期化 | gt init (repo-level) | git town config setup (repo-level) | gh stack init (per-stack) |
| trunk からスタックを開始 | trunk 上で gt create | git town hack <name> | gh stack init + gh stack add |
| 上にブランチを作成 | gt create -am "msg" | git town append <name> (then commit) | gh stack add -Am "msg" |
| 先端を修正して子ブランチをリスタック | gt modify -a | edit, then git town sync --stack | (edit, then gh stack push) |
| 新しいコミットを作成して子ブランチをリスタック | gt modify -cam "msg" | commit, then git town sync --stack | (commit, then gh stack push) |
| スタックを確認 | gt log short (gt ls) | git town branch | gh stack view (-s short) |
| trunk を取得してリスタック | gt sync | git town sync --stack | gh stack sync |
| カスケード状のリスタックのみ | gt restack | git town sync --stack --no-push | gh stack rebase |
| PR を送信/更新 | gt submit --stack (gt ss) | git town propose --stack | gh stack submit |
| 通常の Git ブランチを取り込む | gt track (any time) | git town set-parent (any time) | gh stack init --adopt (init-time only) |
| スタック内を上/下に移動 | gt up / gt down | git town switch (picker) | gh stack up / gh stack down |
| コンフリクト後に続行 | gt continue | git town continue | gh stack rebase --continue |
| 停止した操作を中止/スキップ | gt abort | git town skip / git town undo | gh stack rebase --abort |
| 既存の PR をスタックとして開く | n/a | n/a (set parents, then propose --stack) | gh stack link <PRs...> |
フラグに迷ったときは、記憶ではなく必ず各ツールのリファレンスを参照してください。3 つの CLI はいずれもバージョン間で仕様が変わります。
ルール(3つのツールすべてに適用)
- スタックの途中で
git rebaseに手を出さないでください。 子ブランチが正しい親ブランチにつながったままになるよう、ツールの同期/スタック再構成/変更コマンドを使ってください。 - スタック内のブランチを1つだけ
git pushしないでください。 ツールの送信/プッシュコマンドを使ってください。単独のプッシュでは親ブランチとの関連付けが行われず、スタックの残りが古い状態のままになります。 - ステージングする内容を明示してください。 3つのツールはいずれも
git commitと同様に、ステージングされたファイルを対象にします。ファイル名を指定してステージングし、git add -Aは避けてください。 - ブランチごとに扱う内容は1つにしてください。 これがスタックを使う目的です。各PRを個別にレビューできる状態に保ってください。
- リベースの競合が発生した後は、ツールの
continue/abortを使ってください。git rebase --continue/--abortを直接実行しないでください。そうしないと、ツールのメタデータが更新されません。
引き継ぎ先
- ステージングとコミットメッセージの作成 →
/commit - PRレビュー、CIチェック、マージ、コメント →
/gh - コミット前フックで問題が発生した場合 →
/prek
リファレンスを読むタイミング
references/gt.md—gtコマンドの全機能(作成/変更/同期/送信/追跡/ログ)、インストールと認証、スタック再構成の手順、競合からの復旧、モノレポ/複数のトランクに関する注意事項。検出によってgtが選ばれた場合に読んでください。references/git-town.md—git townコマンドの全機能(hack/append/sync/propose/set-parent/ship)、インストールとフォージ認証、競合からの復旧、設定キー、スカッシュマージに関する注意点。検出によってgit townが選ばれた場合に読んでください。references/gh-stack.md—gh stackコマンドの全機能、インストールとウェイトリスト、終了コード、競合からの復旧、gtとの相違点。検出によってgh stackが選ばれた場合に読んでください。