resolve-merge-conflicts について
チェックアウト中のブランチをベースブランチと同期し、競合を解決して PR の状態を確認するコーディングスキルです。ブランチの積み重ねに応じてリベースまたはマージを選び、意味上の判断が必要な競合ではユーザーに確認します。
主な機能
- 01PR のベースとスタック状態の特定
- 02スタックブランチのリベース、または main のマージ
- 03安全に解決できる競合の判定
- 04doctor の実行と PR 状態の確認
活用シーン
- 01フィーチャーブランチを親 PR と同期
- 02安全な場合に競合する両方の変更を保持
- 03プッシュ前にリベース後またはマージ後の PR を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jasonharmongit/ skills --skill resolve-merge-conflictsインストール後、Claude Code で/resolve-merge-conflictsを入力して読み込まれたか確認します。
詳細
ステップ 1 — ベースブランチを特定する
スタック PR は main ではなく、別のフィーチャーブランチを対象とします。PR がスタックされている状態で main をマージしても、GitHub のコンフリクトは解消されません。
リポジトリのルートから、ベースを特定します。
gh stack view
現在のブランチにオープンな PR がある場合は、ベースを確認します。
gh pr view --json baseRefName,mergeable,mergeStateStatus
baseRefNameがmainではない → スタックされています。ベースはそのブランチです(gh stack viewでこの PR の下にある親 PR)。- PR がない、または
baseRefNameがmain→ ベースはmainです。
ベースブランチ名を <base> として記録します。
スタック全体が直線状になっていることを確認します。GitHub では、各ブランチが直下のブランチの先端に直接連なる必要があります。gh stack view では、リンクが壊れている場合に ⚠ が表示されます。スタックに「branches have diverged」と表示されていても、PR が MERGEABLE である場合があります。
リンクが壊れている場合は、まず下流側を修正します(親から子の順)。親ブランチ(例:admin-search-lookups)のコミットを含んでいない下位ブランチ(例:petal-components)は、その上のブランチをリベースする前にリベースしてプッシュする必要があります。最上位のブランチだけをリベースしても、重複するコミットと分岐のバナーが残ります。
スタック全体を同期する場合は、ブランチを 1 つずつ、ステップ 2~7 を繰り返します。上に進む前に、各ブランチを更新済みの親ブランチにリベースしてからプッシュしてください。
対象範囲 — 現在のブランチのみ
チェックアウト済みのブランチのみを対象に作業します。<base> と同期し、コンフリクトマーカーを解決して、リベースまたはマージを完了し、プッシュします。
ステップ 2 — ベースと同期する
ベースをフェッチしてから同期します。スタックされたブランチは親ブランチにリベースします。main をベースとするブランチは main をマージします。
スタックされています(<base> が main ではない場合):
git fetch origin <base>
git rebase origin/<base>
スタックされていません(<base> が main の場合):
git fetch origin main
git merge origin/main
同期が問題なく完了した場合は、ステップ 5 に進みます。リベースまたはマージが進行中で、コンフリクトが残っている場合は、ステップ 3 に進みます。
ステップ 3 — コンフリクトを確認する
git diff --name-only --diff-filter=U
各ファイルのコンフリクトマーカー(<<<<<<<、=======、>>>>>>>)を読み、各側で何が変更されたかを把握します。リベース中は、ours がベースブランチ(<base>)、theirs が再適用中のコミットを指します。
ステップ 4 — 解決するか、ユーザーに確認する
各コンフリクトについて、次のように判断します。
自動解決するのは、両側の動作をそのまま維持できる場合です。たとえば、両側が異なるインポート、エイリアス、句を追加している場合、同じファイル内で変更箇所が重ならない追加がある場合、片方が書式を変更し、もう片方が別の箇所のロジックを変更している場合などです。両側を統合し、マーカーを削除して、ファイルをステージします。
ユーザーに確認するのは、実際に競合している場合です。同じ動作が異なる方法で実装されている場合、片方がもう片方で依存されているものを削除または名前変更している場合、あるいは両方をマージすると実行時の意味が変わる場合などです。推測してはいけません。処理を中断して、次の内容を報告します。
- ファイルパスとおおよその位置
<base>が行うことと、このブランチが行うこと- どちらかの動作を選ばずに両方を共存させられない理由
実際に競合しているものが残っている場合は、同期を完了しないでください。ユーザーに進め方を確認してください。コンフリクトが解決するまで、ステップ 5~7 はスキップします。
すべてのコンフリクトを自動解決したら:
git add <resolved-files>
次に、進行中の操作を完了します。
- リベース:
git rebase --continue - マージ:
git commit --no-edit
ステップ 5 — Doctor
doctor スキルを見つけて読み、その指示に従います。コンフリクト解決によって直接発生した失敗、またはこのブランチの差分に含まれる変更によって直接発生した失敗のみを修正してください。下流の PR で対応すべき編集が必要な失敗は対象外です。ユーザーから別の指示がない限り、その旨を報告してプッシュを続けてください。同期に関する未解決の意味的な選択が原因の失敗の場合は、推測せずに中断してユーザーに報告します。
ステップ 6 — コミットしてプッシュする
未コミットの変更(doctor による修正、まだコミットしていないコンフリクトの解決など)がないか確認します。
git status --short
ステージされていない変更またはステージ済みの変更がある場合は、作業内容を反映したメッセージ(例:リベースの解決、doctor の修正)でコミットします。
ブランチをプッシュします。リベースでは履歴が書き換えられるため、スタックされたブランチはリース付きでプッシュする必要があります。
# after rebase (stacked branch)
git push --force-with-lease
# after merge (main-based branch)
git push -u origin HEAD # use -u when there is no upstream yet; otherwise plain git push
doctor が合格し、意図した変更がすべてコミットされるまではプッシュしないでください。
ステップ 7 — GitHub で確認する
PR とスタックに問題がないことを確認します。
gh pr view --json mergeable,mergeStateStatus
gh stack view
mergeable は MERGEABLE になっている必要があります。スタック内のどのブランチにも ⚠ が表示されていないことを確認してください。mergeStateStatus が BLOCKED の場合、マージの競合ではなく、CI やレビューの要件が原因である可能性があります。
注意事項
- ユーザーから依頼がない限り、リベースやマージをリセットまたは中止しないでください。
- CLI でのリベースのみを使用してください(
git rebase origin/<base>)。GitLens のインタラクティブリベースを開いたり、git rebase -iを実行したりしないでください。 - 安全に組み合わせられる場合は、片方を選ぶのではなく、両方の意図を保つことを優先してください。
- 競合以外の理由(未コミットの変更が妨げになっている場合など)で同期に失敗した場合は、先にその問題を解決するか、報告してください。
gh stack rebaseはスタック全体をリベースするため、最上位ブランチで失敗することがあります。その場合は、問題のあるブランチを下から順に手動でリベースし、それぞれを--force-with-leaseでプッシュしてから、次の上位ブランチをリベースしてください。