ブランチと手術

スタックブランチ

スタックとは、それぞれが下のブランチの上に積み上がったブランチの連なりです。 main → api → ui のような形です。小さなプルリクエスト 3 つのレビューは、巨大なもの 1 つのレビューに勝ります。

ブランチスタック

Gitcito はこれをルートとして描きます。上に開始ブランチ、その下に階層ごとの停留所が 一つずつ。各停留所の PR はひとつ上の停留所をターゲットにし、最初の停留所は開始ブランチに 着地します。停留所には自分のコミット数、restack が要るかどうか、そして提出後は PR 番号が 並びます。

ルートを編集する

「適用」を押すまで何も実行されません。 ブランチを選ぶ、停留所を動かす、ルートから外す — どれも画面上のリストを編集するだけです。実際の操作はブランチを rebase してチェックアウトする もので、試しに押したクリックがやってよいことではありません。ルートが正しく読めたら、ルートを 適用が取り消し可能な一手として実行します。破棄は、リポジトリが実際に言っている状態へ 描きかけを戻します。

ルートはマージ順に描かれます。上のブランチがひとつ下のブランチにマージされ、最後はスタックの 着地先です。

操作 何が起きるか
開始の欄 スタックの着地先です。変えると鎖全体が新しいブランチへ張り替えられ、再生されます。
停留所の欄 その位置を占めるブランチを差し替えます。ルートから外れたブランチは追跡が外れるだけで、削除はされません。
↑ / ↓ 停留所を一つ分だけ動かします。
✕ 停留所をルートから外します。前後の停留所がつながります。
停留所を追加 すでにあるブランチを選べばルートの先頭に加わります。存在しない名前を打てば、最後の停留所の先端に作られてチェックアウトされます。
矢印のボタン その停留所をチェックアウトします。

どの欄も入力補完つきです。打てば絞り込み、↑/↓ と Enter で確定、一覧にない文字列もその まま通るので、origin/main のようなリモート追跡参照も開始ブランチにできます。

内部ではこれらの編集はすべて同じ操作です — ルート全体を一度に渡すだけ。だからひとつの 操作がひとつの取り消し(⌘Z)になり、途中まで適用されたリンクの残骸になりません。

ルート編集の代償

順序を変えるもの(入れ替え、移動、別の開始点)はすべて鎖を再生します。各停留所自身の コミットが新しいベースの上に rebase されるからです。したがって restack と同じように 衝突しえます。同じ行に触れる二つの停留所は、人手なしには入れ替われません。そのときは 何も起きません。編集全体が巻き戻され(先端も、親リンクも、途中まで進んだ rebase も)、 ぶつかった二つの停留所の名前が示されます。軽く触れたドロップダウンで rebase の途中に取り 残されるべきではありません。

Restack はその取り決めのもう半分です。名指しで頼んだ rebase なので、衝突で止まって衝突 ビューを渡します。それは Gitcito が断った並べ替えを実現する道でもあります — そこで解決して から、停留所を動かしてください。

取り消しは以前のルートを再生します。古いコミットを蘇らせるわけではありません — 新しい コミットは親が違うだけの同じ仕事だからです。

すべてプッシュ

すべてプッシュは各レベルを --force-with-lease でプッシュしてそこで止まります — 何も開かない gh stack push です。下のスタックを PR として提出は同じプッシュに加えて PR の作業まで行います。リモートにブランチは置きたいがレビューはまだ、というときは すべてプッシュを使ってください。

スタックを連鎖プルリクエストとして提出する

提出はまず尋ねます。いくつプルリクエストを作成し、いくつのターゲットを変更するのか、どの リモートに対してか、そして各行の ブランチ → ベース を。プルリクエストを開くのは公開の行為で、 取り消すのは面倒だからです。各本文に 書き込まれるナビゲーション節こそが、スタックという概念を持たない GitHub 上で鎖を見えるように します。

提出は専用の画面で行います。まず計画、次に一歩ずつの進捗、最後に各プルリクエストとスタック 自体へのリンクです。

スタックの提出

スタックを PR として提出 は、スタック用ツールが有料で売っている作業をワンクリック でこなします。

  1. すべての段を --force-with-lease でプッシュします(新しいブランチはそのままでも 通りますが、リスタック済みのブランチにはこれが必要です)。
  2. プルリクエストのない段すべてにプルリクエストを開きます — それぞれの宛先は main ではなく 親のブランチ なので、どのレビューにも自分のコミットだけが表示されます。 タイトルと説明はその段自身のコミットから作られます。
  3. ベースがずれてしまった既存のプルリクエストの宛先を付け替えます。
  4. すべてのプルリクエスト本文に スタックナビゲーションのセクション を書き込むので、 どの段のレビュアーも連鎖全体と、そのプルリクエストがその中のどこにあるのかを見渡せ ます。

この操作は 冪等 です。リスタック、段の追加、プルリクエストのマージのたびに押しても 結果は収束します — 何も重複せず、ずれたものだけが更新されます。

いちばん下のプルリクエストがマージされたら、同じボタンが後片付けまで引き受けます。 マージ済みの段の子はトランクの上に付け替えられ、その段は追跡解除され、ローカルブランチ は削除され(トランクがそれを含むことが証明できるので安全です)、連鎖はリスタックされ、 残りのプルリクエストはすべて宛先が付け替えられます。下から順にマージして、提出を押して、 繰り返してください。

GitHub では本物のスタックにもなります

ベースの連鎖はどのホストでも通じる形で、GitLab・Bitbucket・Azure DevOps ではそれが すべてです。GitHub にはその先があります。stacked pull requests のプレビュー以降、 スタックはサーバー上のオブジェクトです。プルリクエストができたあと、Gitcito はそれらを 下から上へスタックとして登録します。PR 画面のスタックマップ、サーバー側のカスケード rebase、そして一番上の PR をマージすれば下の未マージのレベルもまとめて着地する挙動が 手に入ります。

リポジトリがそのプレビューに入っていない場合や、トークンにスタックを操作する権限が ない場合は、この呼び出しは黙って飛ばされます。連鎖とナビゲーション節はそれだけで 成立します — ほかのホストとまったく同じように。

リスタック

下のブランチが変わったとき — api でレビュー指摘に対応した、というような場合 — その上の ブランチはどれも間違ったベースの上に乗っています。リスタック は rebase --onto で 連鎖全体をリベースし直すので、親を書き換えても子にコミットが重複しません。リスタックの あとにもう一度 提出 を押してください。書き換えられた段が強制プッシュされ、プル リクエストはその場で更新されます。

制限

  • 提出は今のところ GitHub のみ です(作成は 4 つのホストすべてで動きますが、宛先の 付け替えと本文の更新には GitHub API が必要です)。
  • いちばん下のマージ後の後片付けは、マージとリベースによるマージを祖先関係から検出し、 スカッシュマージは、そのブランチのプルリクエストが取り込まれたかどうかを GitHub に 問い合わせて検出します — つまり GitHub トークンがあれば、どのマージ方式でも後片付け されます。他のホストの場合や、トークンがない場合は、スカッシュマージされた段は今まで どおり手動での追跡解除が必要です。また、先にフェッチしてください — 祖先関係の確認は、 最後にフェッチした時点のトランクを読みます。
  • プルリクエスト本文のスタックセクションは隠しマーカーの間で管理されるので、その上に 書いたあなた自身の説明は保持されます。
  • 並べ替えとトランクの変更は、触れたすべてのレベルで履歴を書き換えます。ブランチは あなたのもので、未プッシュのレベルなら痛みはありませんが、すでにレビュー中のレベルは 次の提出で強制プッシュを受けます。
  • レベルは一度に一段しか動きません。二回の入れ替えは二回の rebase であり、途中で止まった 状態も読み取れます。三つ先に着地するドラッグはそうはいきません。
  • 停留所は rebase されます。だからスタックが着地するブランチが同時に停留所になることは なく、保護されたブランチ(リストを変えていなければ main と master)も停留所には なりません。どちらも、共有の履歴を黙って書き換える代わりに拒否されます。
  • 提出は何かを開く前に、どのブランチが本当にリモートへ届いたかを尋ね、届かなかったものを 名指しします。head が見つからないとき GitHub が返すのは素っ気ない "Validation Failed" だけで、それは誰の役にも立ちません。 スタックの着地先ブランチも確認します。ローカルにしかない場合は、プッシュして続行するかを 提出が尋ねます。

つながりが保存される場所

親へのつながりは git config に保存されるので、リポジトリと一緒に移動し、クローンし 直しても残ります。どこかのサービスに置かれるものはありません。

関連項目: 対話的リベース · ホスティングとプルリクエスト

この翻訳を GitHub で改善