GitHubでスタックされたプルリクエストを操作する際、スタックの構造を変更する必要がよくあります - ブランチの並べ替え、結合、名前変更など。GitHub CLI拡張機能のgh stackは、これを簡単に行うための強力なツールを提供します。
問題#
スタックされたPRを使用して機能を開発する際、以下のような状況によく遭遇します:
- ブランチをスタック内の上位または下位の位置に移動する必要がある
- 2つのブランチを結合したい
- PRを保持したままブランチをスタックから削除する必要がある
- 既存のブランチの間に新しいブランチを挿入したい
- ブランチの名前を変更して内容をより正確に反映させたい
複雑なgit rebaseとforce push操作を手動で行う代わりに、gh stackは専用のコマンドを提供します。
解決策#
GitHub CLIは、スタックを再構築するための2つの主要なアプローチを提供します:
1. gh stack modifyを使用する(推奨)#
このコマンドは、構造的な変更を行い、すべてを一度に適用できる対話型ターミナルUIを開きます。
gh stack modifybashTUIインターフェースは以下のキーバインディングをサポートします:
| キー | アクション | 説明 |
|---|---|---|
x | Drop | ブランチとそのコミットをスタックから削除 |
d | Fold down | ブランチを下のブランチに吸収(trunk方向) |
u | Fold up | ブランチを上のブランチに吸収(trunkから離れる方向) |
i | Insert below | 下に新しい空のブランチを挿入(trunk方向) |
I | Insert above | 上に新しい空のブランチを挿入(trunkから離れる方向) |
Shift+↓ | Move down | ブランチを下に移動(trunk方向) |
Shift+↑ | Move up | ブランチを上に移動(trunkから離れる方向) |
r | Rename | ブランチの名前を変更(インラインプロンプトを開く) |
z | Undo | 最後のステージされたアクションを取り消し |
Ctrl+S | Apply | すべての変更を適用 |
2. gh stack unstack + gh stack initを使用する#
より手動なアプローチですが、複雑な変更には柔軟です:
# 1. 現在のスタックを削除
gh stack unstack
# 2. 構造的な変更を手動で行う
git branch -m api-routes api-endpoints
git branch -d feature-removed
# 3. 新しい構造でスタックを再作成
gh stack init db-migrations api-endpoints frontendbash再構築ワークフロー#
スタックを再構築するワークフローは以下の通りです:
flowchart TD
A[現在のスタック] --> B{方法?}
B -->|対話的| C[gh stack modify]
B -->|手動| D[gh stack unstack]
C --> E[TUIを開く]
E --> F[アクションを選択]
F --> G[変更をステージ]
G --> H{完了?}
H -->|いいえ| F
H -->|はい| I[Ctrl+Sで適用]
D --> J[手動変更]
J --> K[git branch -m/-d]
K --> L[gh stack init]
I --> M[カスケーディングrebase]
L --> M
M --> N[gh stack push]
N --> O[再構築されたスタック]
実用的な例#
例1:ブランチを上位に移動する#
下から上へのスタックがあるとします:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[frontend]
D --> E[testing]
testingをapi-routesの上に移動したい場合:
gh stack modify
# Shift+↑を使用してtestingを上に移動
# Ctrl+Sで適用bash結果:
graph TD
A[main] --> B[db-migrations]
B --> C[testing]
C --> D[api-routes]
D --> E[frontend]
例2:2つのブランチを結合する#
2つのブランチを結合すべきだと気づいた場合:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[api-validation]
D --> E[frontend]
api-validationをapi-routesにfoldする:
gh stack modify
# api-validationを選択し、d(fold down)を押す
# Ctrl+Sで適用bash結果:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes + validation]
C --> D[frontend]
例3:新しいブランチを挿入する#
既存のブランチの間にレイヤーを追加する必要がある場合:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[frontend]
api-routesとfrontendの間にauth-middlewareを挿入:
gh stack modify
# カーソルをapi-routesに置く
# I(insert above)を押す
# 新しいブランチに名前を付ける
# Ctrl+Sで適用bash結果:
graph TD
A[main] --> B[db-migrations]
B --> C[api-routes]
C --> D[auth-middleware]
D --> E[frontend]
カスケーディングrebaseプロセス#
gh stack modifyで変更を適用すると、以下のプロセスが発生します:
sequenceDiagram
participant User as あなた
participant CLI as gh stack modify
participant Git as Git
participant Remote as GitHub Remote
User->>CLI: gh stack modify
User->>CLI: 変更をステージ(移動/fold/挿入)
User->>CLI: Ctrl-Sで適用
CLI->>Git: 必要に応じてブランチ名を変更
CLI->>Git: 必要に応じて新しいブランチを挿入
CLI->>Git: カスケーディングrebase
loop 各ブランチについて
CLI->>Git: 現在のブランチを下のブランチにrebase
Git-->>CLI: Rebase完了
end
CLI->>User: 成功通知
User->>CLI: gh stack push
CLI->>Remote: Force push with `\-\-force-with-lease`
Remote-->>CLI: Push成功
CLI-->>User: GitHubでスタックが更新されました
重要な注意点#
[!WARNING]
- マージされたPRのブランチは変更できません
- 構造的な変更(drop、fold、insert、rename)は同じセッションで混在できません
- 安全のため常に
--force-with-leaseでgh stack pushを使用してください- 大規模な再構築の前に重要なブランチをバックアップしてください
ベストプラクティス#
- 現在のスタックを確認:変更前に常に
gh stack viewを実行 - TUIを使用:
gh stack modifyは適用前に変更をプレビューできるため安全 - ローカルでテスト:プッシュ前にrebaseが成功することを確認
- コミュニケーション:主要なスタック構造変更についてチームに通知
- バックアップ:重要なスタックのタグまたはブランチバックアップ