mergify-stack について
mergify-stack は、Mergify CLI で Git ブランチを短く依存関係のあるスタックとして管理するワークフロースキルです。コーディングエージェント向けにスタック編集と PR 更新の手順を示し、各コミットが単独で CI を通ることを求めます。
主な機能
- 01スタックブランチと PR の作成・更新
- 02スタック同期とコミット・PR 状態の確認
- 03非対話型コマンドによるコミットの書き換え
- 04コミットメッセージと PR 内容の連動
- 05単独で CI を通るコミットとドラフト PR
活用シーン
- 01無関係な作業を別ブランチに分割
- 02マージ後に既存スタックを同期
- 03エージェントセッションでコミットを修正・並べ替え
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mergifyio/ mergify-cli --skill mergify-stackインストール後、Claude Code で/mergify-stackを入力して読み込まれたか確認します。
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
Mergify スタックワークフロー
スタックの考え方
ブランチはスタックです。スタックは短く、焦点を絞って保ちましょう:
- スタックには、互いに依存し合うコミットのみを含めるべきです
- 理由:スタックが長くなるほど、マージに時間がかかります
プロアクティブなスタック管理:
- 既存のスタックを独立したスタックに分割できる場合は、分割を提案してください
- 新しいことを依頼されたとき:別のブランチで実行できる場合は、そうするか、不明な場合は確認してください
- 無関係な変更には、デフォルトで新しいブランチを作成してください
基本的な規約
- プッシュ:
mergify stack pushを使用してください(git pushは決して使用しないでください) - 修正:
git commit --amendを使用してください(問題を修正するために新しいコミットを作成しないでください) - amend 時の注記: すでに PR があるコミット(つまりプッシュ済みのコミット)を amend する場合、
mergify stack pushの前にmergify stack noteを付けて、そのコミットをなぜ amend したのかを記録してください。この注記は PR の「Revision history」コメントと JSON マーカーに表示されるため、レビュアーは差分を見なくても理由を確認できます。 - スタック途中の修正: まずローカルの変更をすべてスタッシュし(
git stash -u)、次にmergify stack edit <SHA-or-Change-Id-prefix>を使って対象コミットで rebase を一時停止します。git commit --amendで amend し、その後git rebase --continue、続いてmergify stack push、最後にgit stash popを実行します。非対話式です — この用途でgit rebase -iは決して使用しないでください。(mergify stack editを引数なしで呼び出すと、完全に対話式のgit rebase -iにフォールバックし、エージェントのコンテキストではハングします — 必ずコミットのプレフィックスを渡してください。) - 並べ替え: まずローカルの変更をすべてスタッシュし(
git stash -u)、次に手動のgit rebase -iの代わりにmergify stack reorder(すべてのコミットを希望する順序で列挙)またはmergify stack move(単一のコミットを移動)を使用してください — 非対話式で、GIT_SEQUENCE_EDITORのクォート問題を回避できます - Fixup: まずローカルの変更をすべてスタッシュし(
git stash -u)、次にmergify stack fixup <SHA>...を使ってコミットをその親に折り込みます(列挙したコミットのメッセージは破棄されます)。非対話式です — この用途でgit rebase -iは決して使用しないでください。 - Squash: まずローカルの変更をすべてスタッシュし(
git stash -u)、次にmergify stack squash SRC... into TARGET [-m "msg"]を使って複数のコミットを 1 つに結合します。任意でカスタムメッセージを指定できます。非対話式です — この用途でgit rebase -iは決して使用しないでください。 - Reword: まずローカルの変更をすべてスタッシュし(
git stash -u)、次にmergify stack reword <SHA> -m "new message"を使ってコミットのメッセージをその場で変更します。-mを指定した場合は非対話式です — この用途でgit rebase -iは決して使用しないでください。 - Drop: まずローカルの変更をすべてスタッシュし(
git stash -u)、次にmergify stack drop <SHA>...を使ってスタックからコミットを削除します。非対話式です — この用途でgit rebase -iは決して使用しないでください。 - コミットのタイトル: Conventional Commits に従ってください(例:
feat:,fix:,docs:) - PR のタイトルと本文:
mergify stackはコミットメッセージのタイトルを PR のタイトルに、コミットメッセージの本文を PR の本文にコピーします — そのため、コミットメッセージは PR の説明であるかのように書いてください。PR に表示されるべきものすべて(チケット参照、コンテキスト、テスト計画)は、必ずコミットメッセージに含めてください。 - チケット参照: チケットやイシューの参照(例:
MRGFY-1234、Fixes #123)はコミットメッセージの本文に含めてください。PR に別途追加しないでください。 - PR のライフサイクルは
mergify stackが完全に管理します:gh pr editや GitHub MCP で PR のタイトル、本文、ラベルを決して編集しないでください — 次のプッシュで上書きされます。PR を手動でクローズまたはマージしないでください —mergify stackが PR のライフサイクル全体(作成、更新、クリーンアップ)を処理します。 - ドラフト PR: PR を ready-for-review に決してしないでください — すべての PR はドラフトのままにします。ユーザーがレビュー後に手動でドラフトを解除します。
- 各コミットは単独で CI を通過する必要があります: スタック内のすべてのコミットはそれぞれ独立した PR になります。各 PR は個別に CI を実行するため、すべてのコミットは自己完結していなければなりません — スタック内の後続のコミットに依存せず、単独でコンパイルし、リンターを通過し、テストを通過する必要があります。フォーマットやリンティングの修正が必要な場合は、それを問題を導入したコミットに含める必要があり、後続のコミットに先送りしてはいけません。
よくある間違い
| 間違い | 正しい方法 | 理由 |
|---|---|---|
git push | mergify stack push | git push はスタック管理をバイパスし、PR の関係を壊します |
| lint/タイポを修正するための新しいコミット | git commit --amend(HEAD)または git commit --fixup <SHA> + git rebase --autosquash(スタック途中) | 各コミット = 1 つの PR。修正コミットは不要な追加 PR を生み出します |
gh pr edit --title "..." | コミットメッセージを編集してから mergify stack push | PR のタイトル/本文はプッシュのたびにコミットメッセージから上書きされます |
gh pr merge または gh pr close | PR のライフサイクルは完全に管理されているため、何もしない | PR のライフサイクルはスタックツールによって完全に管理されます |
main 上での git commit | まず mergify stack new <name> | mergify stack push はデフォルトブランチでは失敗します |
コミットを修正するための git rebase -i | mergify stack fixup <SHA> | 非対話型 — LLM/エージェントセッション内で動作し、エディタが起動されません |
コミットを squash するための git rebase -i | mergify stack squash A B into X [-m "..."] | 非対話型 — LLM/エージェントセッション内で動作し、エディタが起動されません |
コミットメッセージを変更するための git rebase -i | mergify stack reword <SHA> -m "..." | 非対話型 — LLM/エージェントセッション内で動作し、エディタが起動されません |
スタック途中のコミットを修正するための git rebase -i | mergify stack edit <SHA-or-Change-Id-prefix> の後に git commit --amend、そして git rebase --continue | 非対話型 — エディタを起動せずに対象コミットで rebase を一時停止します |
コミットを削除するための git rebase -i | mergify stack drop <SHA>... | 非対話型 — LLM/エージェントセッション内で動作し、エディタが起動されません |
GIT_SEQUENCE_EDITOR='sed -i ...' git rebase -i(あらゆる変種) | mergify stack {edit,fixup,squash,reorder,move} のいずれか | 手作りのシーケンスエディタスクリプトは壊れやすく、一般的な書き換えにはすでに非対話型のコマンドが存在します |
| lint 修正を後続のコミットに先送りする | その原因となったコミットに修正を含める | 各コミットは独立して CI を実行するため、後続のコミットが以前のコミットを救うことはありません |
| ダーティなワークツリーでの rebase/reorder/checkout/sync | まず git stash -u を実行し、その後 git stash pop | コミットされていない変更はこれらの操作中に失われるか、競合を引き起こします |
| 説明なしでプッシュ済みコミットを amend する | mergify stack push の前に mergify stack note -m "why" | 理由が PR の Revision history テーブルと JSON マーカーに記録されるため、レビュアーは差分を見なくても変更を理解できます |
コマンド
mergify stack new NAME # Create a new stack/branch for new work
mergify stack push # Push and create/update PRs (also registers as a GitHub-native stack by default)
mergify stack push --no-github-native # ...without registering it as a GitHub-native stack
mergify stack checkout BRANCH # Checkout an existing stack from GitHub (e.g. someone else's)
mergify stack checkout PR_URL # Same, from any PR in the stack — middle included
mergify stack sync # Fetch trunk, remove merged commits, rebase
mergify stack list # Show commit <-> PR mapping for current stack
mergify stack list --json # Same, but machine-readable JSON output
mergify stack reorder C A B # Reorder all commits (pass SHA or Change-Id prefixes)
mergify stack move X first # Move commit X to the top of the stack
mergify stack move X last # Move commit X to the bottom of the stack
mergify stack move X before Y # Move commit X before commit Y
mergify stack move X after Y # Move commit X after commit Y
mergify stack fixup X # Fold commit X into its parent (drops X's message)
mergify stack fixup X Y Z # Fold each into its parent (multi-fixup)
mergify stack squash X into Y # Reorder X adjacent to Y, fold X into Y (keeps Y's message)
mergify stack squash X Y into Z -m "msg" # Fold X Y into Z with a custom message
mergify stack reword X -m "msg" # Change commit X's message non-interactively
mergify stack reword X # Change commit X's message via $GIT_EDITOR (TTY only)
mergify stack edit X # Pause the rebase at X so you can `git commit --amend` it (X is required; no-arg form is interactive)
mergify stack drop X # Drop commit X from the stack
mergify stack drop X Y Z # Drop multiple commits in one rebase
mergify stack note -m "why" # Attach an amend reason to HEAD (shown in PR revision history)
mergify stack note <SHA-or-Change-Id-prefix> -m "why" # Attach to a specific commit in the stack
mergify stack note --append -m "more" # Append to an existing note
mergify stack note --remove # Remove the note from a commit
mergify stack checkout を使用すると、GitHub 上に存在するスタック(たとえば同僚のスタック)をチェックアウトできます。引数には、スタックのリモートブランチ名(どのようなプレフィックスであってもよく、作者名が含まれているとは想定しません)、またはスタック内の任意のプルリクエストの URL(途中のものを含む)を指定します。スタックされたすべての PR をフェッチし、ローカルブランチを作成して、トラッキングを設定します。
ローカルブランチの名前は、デフォルトではスタックブランチから自分のスタックブランチプレフィックスを除いたものになるため、feature/login からプッシュしたスタックは feature/login として戻り、その後の mergify stack push で同じ PR が更新されます。自分のプレフィックス配下にないスタック(同僚のもの)の場合は、最後のセグメントが使用され、チェックアウト時に警告が表示されます。それらのコミット上で作業することはできますが、そのブランチから mergify stack push を実行すると、同僚のプルリクエストを更新するのではなく、別のスタックが作成されます。名前を上書きするには --branch を使用します。プルリクエストの URL にはそれ自体の owner/repo が含まれるため、その形式では --repository は無視されます。
mergify stack sync を使用すると、スタックを最新の状態にできます。最新のトランクをフェッチし、マージされた PR を検出し、それらのコミットをローカルブランチから削除して、残りのコミットをリベースします。既存のスタックで新しい作業を始める前に実行してください。
mergify stack list を使用すると、どのコミットがプッシュ済みか、それらがどの PR に対応するか、スタックがリモートと同期しているかを確認できます。各 PR の CI ステータス、レビューステータス、マージコンフリクトも表示されます。詳細なチェック名とレビュアー名を表示するには --verbose を使用します。出力をプログラムで解析する必要がある場合は --json を使用します。これには完全な CI チェックの詳細とレビューデータが含まれます。
GitHub ネイティブスタック(デフォルトで有効)
mergify stack push はデフォルトでスタックを GitHub 自身の Stacks API に登録するため、GitHub はそれをスタックとしてレンダリングします。呼び出しごとに --no-github-native でオプトアウトするか、リポジトリごとに
git config mergify-cli.stack-github-native false でオプトアウトできます。
Change-Id、ブランチレイアウト、リビジョン履歴は変わらず、静かに機能を縮退させます。API が利用できない場合(古い GitHub Enterprise、この機能を持たないリポジトリ)には、プッシュは not registered on GitHub と報告し、これまでとまったく同じように成功します。
知っておくべき 3 つのこと:
- スタックには少なくとも 2 つのプルリクエストが必要です。 GitHub は 1 つの PR のスタックを拒否するため、単一の変更のスタックは通常の PR のままです。また、メンバーを失った 2 つの PR のスタックは再登録されるのではなく解散されます。
Depends-On:ヘッダーはなくなります。 登録されたスタックは まさに 2 つのプルリクエスト間の依存関係であるため、CLI はそのコピーを PR の説明に二重に書き込むのをやめます。これはフラグではなく登録に基づいて決まります。プッシュがnot registered on GitHubに縮退した場合、ヘッダーは同じプッシュ内で書き戻され、Mergify はスタックの順序付けを続けます。どちらの場合でもコミットメッセージには一切触れません。ヘッダーは常に、レンダリングされた PR の説明の中にのみ存在していました。- スタックのコメントもなくなります。 GitHub は登録されたスタックのメンバーをプルリクエストページに一覧表示するため、CLI は「This pull request is part of a Mergify stack」という固定の表を投稿するのをやめ、古いプッシュが各オープンメンバーに残したものを削除します。ヘッダーと同じく登録に基づいて決まります。縮退したプッシュは表の投稿と更新を続けます。なぜなら、それ以外にスタックを示すものがないからです。リビジョン履歴のコメントはどちらの場合でも変更されません。GitHub はそれに似たものを何もレンダリングしません。
- 登録は PR のマージ方法を変えます。 スタックが登録されている間、GitHub はそのメンバーに対して従来のマージエンドポイント
(
PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge→ 403) を拒否します。これは GitHub の契約であり、私たちのものではありません。これが--no-github-nativeが存在する理由です。
プッシュは低コストのままです。コミットのリフレッシュ(amend、reword、force-push)は登録をそのままにし、変更を上に追加すると同じスタックが拡張されます。プルリクエストのベースを移動させるプッシュ(並べ替え、削除、途中への変更の挿入)だけが、まず登録を解散し、最後に再構築します。なぜなら GitHub は PR がスタックされている間、ベースブランチの変更を一切拒否するからです。したがって、中断されたプッシュはスタックを単に未登録のままにします——半分登録された状態には決してなりません。また、Depends-On: ヘッダーが失われたままになることもあります。これらはプッシュの最後に復元されるためです。mergify stack push を再実行すれば両方とも解決します。すべてのプッシュが説明を再レンダリングし、スタックの現在の形状から Depends-On: マーカーを再計算するからです——--keep-pull-request-title-and-body を使用した場合も同様で、その場合の説明はコミットメッセージではなくプルリクエスト自身の本文から再レンダリングされ、マーカーは引き継がれるのではなく、依然として削除されて再追加されます。
修正ノート
mergify stack note は、コミットがなぜ修正されたかを記録します。ノートはスタックとともに移動します:
- 理由はコミット SHA に対して
refs/notes/mergify/stackの下にローカルに保存されます。 mergify stack push時に、理由はチェンジのリビジョン履歴に取り込まれます。プッシュされた先頭コミットのノートは、リビジョン履歴全体 (人間が読めるダイジェスト + `` JSON マーカー) に置き換えられます。機械可読な信頼できる情報源は PR コメントではなく Git notes です。PR の「リビジョン履歴」コメントはそれらからレンダリングされます。- マージ時に、Mergify は先頭コミットの履歴ノートをマージ/スカッシュコミットにコピーするため、ベースブランチで
git log --notes=mergify/stackを実行すると、各チェンジがなぜ改訂されたかが表示されます。
ノートを付けるタイミング — すでに PR がオープンされている (つまり少なくとも一度はプッシュされている) コミットを修正または書き換えるたびに。ノートは「なぜこのリビジョンは異なるのか?」に答えるもので、レビュアーが新旧の SHA を diff して調べる必要がなくなります。
ワークフロー — mergify stack push の前にノートを付けます:
# Edit HEAD, then:
git commit --amend
mergify stack note -m "address review: rename foo() to bar()"
mergify stack push
# Or for a mid-stack commit (after the rebase that amended it):
mergify stack note <SHA-or-Change-Id-prefix> -m "fix lint reported in CI"
mergify stack push
ノートはリビジョン単位ではなくコミット単位です。修正 (またはその他の履歴書き換え) のたびに新しいコミット SHA が作成されるため、新しい SHA に対して再度 mergify stack note を実行する必要があります。以前のノートは古い SHA に付いたままで、引き継がれることはありません。--append は、現在の対象コミットにすでにノートがあり、別の理由を追加したい場合にのみ使用してください。--remove はノートをクリアするために使用します。最後のプッシュ以降に変更されていないコミットのノートは保持されますが、新しいリビジョン行は追加されません。
重要: コミットする前に必ずブランチを確認する
何かをステージまたはコミットする前に、常に現在のブランチを確認し、スタックの状態を評価してください:
git branch --show-current
mergify stack list
main(またはリポジトリのデフォルトブランチ) にいる場合: まずフィーチャーブランチを必ず作成する必要がありますmainに直接コミットしないでください —mergify stack pushが失敗します- この確認は
git commitの後ではなく、git addの前に実行する必要があります
重要: ワークツリーを変更する操作の前にローカルの変更を stash する
履歴を書き換えたりブランチを切り替えたりする操作を実行する前に、コミットされていない変更がないか確認し、stash してください:
git status --short # Check for uncommitted changes
git stash -u # Stash tracked + untracked changes if any
この確認が必要な操作:
mergify stack edit <commit>(スタック途中の修正)mergify stack reorder/mergify stack movemergify stack fixupmergify stack squashmergify stack rewordmergify stack dropmergify stack checkoutmergify stack syncmergify stack new(新しいブランチに切り替えます)git checkout <branch>
操作が完了したら、stash した変更を復元します:
git stash pop
この手順を省略すると、コミットされていない作業は気づかないうちに失われるか、リベースの競合を引き起こします。
新しい作業の開始
新しい作業を開始する、新しいフィーチャーを作成する、または現在のスタックと無関係な何かに取り組むよう依頼された場合:
- 現在のブランチを確認:
git branch --show-current - 新しいスタックを作成:
mergify stack new <branch-name>- パターン
type/short-description(例:feat/add-login、fix/memory-leak) に従った説明的なブランチ名を使用してください
- パターン
- コミットを作成: conventional commits に従ってください
- プッシュ:
mergify stack push
既存のスタックへの追加
既存のフィーチャーブランチでの作業を続ける場合:
- 現在のブランチを確認:
git branch --show-current- 正しいブランチにいる場合: そのままコミットを進めます
mainにいる場合: まずgit checkout <branch>でフィーチャーブランチに切り替えるか、新しいスタックを作成してください
競合の解決
リベースが競合を引き起こした場合 (git rebase -i または mergify stack push 中):
- エディターで競合を解決します
- 解決したファイルを
git addでステージします git rebase --continueで続行します
中止する場合: git rebase --abort
解決後、mergify stack push を実行して更新されたスタックを同期します。