# 1natsu Pair Resolve Conflicts

> Gitのコンフリクト解消を人間とペアで行う協調スキル。merge / rebase / cherry-pick / stash pop で衝突した時、コミット履歴と変更の経緯を分析し、「なぜこう変わったか」を解説しながら1つずつ人間の承認を得て解消する。マーカーを消すだけでなく、両側が実装した機能を壊さない統合を前提に解消案を出す。すでに衝突している場合だけでなく、stale な PR（mergeable:false）で未コンフリクトの状態からでも、承認のうえ base 追従でコンフリクトを発生させて始められる。ユーザーが「コンフリクト解消しよう」「一緒にコンフリクト直そう」「conflict resolve」「stale な PR を base 追従して一緒に解消」等、またはAIがコンフリクト検知時に使う。自動で一括解消してコミットせず、必ず人間と対話しながら進めること。

- Skill: `1natsu-vacation/1natsu-pair-resolve-conflicts` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 1natsu-vacation/1natsu-pair-resolve-conflicts`
- Raw SKILL.md: https://api.skillmd.com/api/skills/1natsu-vacation/1natsu-pair-resolve-conflicts/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: 1natsu-vacation (https://skillmd.com/u/1natsu-vacation)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/1natsu-vacation/1natsu-pair-resolve-conflicts

---


# Pair Resolve Conflicts（ペアコンフリクト解消）

コンフリクトの背景にあるコミット履歴と意図を読み解き、人間と一緒に1つずつ解消していく協調モード。

AIは変更の経緯調査・解消案の提示・解消後の整合性確認を担当し、人間は最終的な解消方針の判断と承認を担当する。AIが勝手に全コンフリクトを解消してコミットすることは絶対にしない。

## このスキルが言う「解消」の定義（相互機能保持）

コンフリクトマーカーを消すことはゴールではない。**マーカーの除去 + 両側の機能を壊さない整合**が揃って初めて「解消」と呼ぶ。ours と theirs が**それぞれ別の機能を実装している**のに片側を丸ごと捨てる解消案は、マーカーは消えても**もう一方の機能を黙って捨てるデグレ**。解消案を出すときは、片側採用で失われる機能があるなら必ずそれを明示し、両側が機能追加しているなら**統合・移植を第一案**にする（詳細は Phase 2 Step 2）。

## 起点の2パターン

1. **すでにコンフリクト状態** — `git status` に unmerged paths がある。→ Phase 0 から。
2. **未コンフリクト状態だが追従が必要** — stale な PR（`mergeable:false`）等で、base 追従するとコンフリクトが起きる。→ **Phase A** で人間の承認を得てから base 追従し、コンフリクトを発生させて Phase 0 に合流する。

## 対話ルール

ユーザーに選択肢を提示する場面では、プラットフォームが提供する対話型の選択UIを使うこと。

## モードの開始

### ユーザーからの明示的な起動

以下のようなフレーズで要求された場合、即座にモードに入る：

- 「コンフリクト解消しよう」「一緒にコンフリクト直そう」「pair resolve」「conflict resolve」
- 「マージしたらコンフリクトした」「rebase でコンフリクト出た」
- 「stale な PR を base 追従して一緒に解消しよう」「mergeable false を一緒に直そう」（→ 未コンフリクト状態なら Phase A から）

### AIからの提案

コンフリクト状態を検知した場合（`git status` で `both modified` / `both added` / `deleted by us` 等が見える、ユーザーがコンフリクトについて言及している等）、このモードへの移行を**提案する**（勝手に入らない）。

提案の例：

> コンフリクトが発生しているようです。コミット履歴を確認しながら一緒に解消しませんか？

以下の選択肢を提示する：

- 「はい、一緒に解消しましょう」→ モードに入る
- 「いいえ、自分で対応する」→ モードに入らず、通常の対応に戻る

## ワークフロー

### Phase A: 追従の起点作り（未コンフリクト状態からの起動時のみ・要承認）

`git status` に unmerged paths が**なく**、かつ「stale な PR を base 追従して解消したい」という起点の場合に通る。すでにコンフリクト状態なら飛ばして Phase 0 へ。

auto モードと違い、**fetch / merge を実行する前に必ず人間の承認を取る**。手順：

1. **前提確認** — 進行中の git 操作がないこと、ワーキングツリーが clean なこと（未コミット変更があれば「先に commit / stash しましょう」と伝える）。
2. **base ブランチの特定と提示** — `gh pr view --json baseRefName,mergeable,mergeStateStatus`（あれば）→ `@{upstream}` / default ブランチ、の順で base を割り出し、「`origin/<base>` に追従するとコンフリクトが出る見込みです。`git merge origin/<base>` で追従しますか？」と提示する。base が確定できなければ人間に尋ねる。
3. **承認後に追従を実行** — 既定は `git fetch origin <base>` → `git merge origin/<base>`（force-push 不要・PR レビュー履歴が剥がれないため）。**remote が無い / `origin` が無い場合は `git fetch` を飛ばし、ローカルの base ブランチを直接取り込む（`git merge <base>`）**。ローカル base も無ければ人間に確認する。
   - コンフリクトなしで完了 → 追従できた旨を報告（解消対象なし）。
   - コンフリクト発生 → Phase 0 に合流して通常どおり進める。

追従戦略の根拠・base 検出の詳細は auto スキルの `references/stale-pr-follow.md`（同梱）を共通知識として参照してよい。

### Phase 0: 状況把握

モード開始時に以下を確認する：

```bash
# 現在の状態（merge中? rebase中? cherry-pick中?）
git status

# rerere が有効か確認
git config rerere.enabled
```

**rerere（reuse recorded resolution）が有効な場合：**

- `git rerere status` で既に自動解消された箇所を確認する
- rerere が適用済みのファイルがあれば「rerere が以前の解消を再適用しました」と伝え、内容を人間に確認してもらう
- rerere の自動解消が正しいか怪しい場合は `git rerere forget <file>` で取り消すことを提案する
- rerere が有効でない場合は特に言及不要（有効化の提案もしない。設定はユーザーの判断領域）

### Phase 1: コンフリクト全体の俯瞰

```bash
# コンフリクトしているファイル一覧
git diff --name-only --diff-filter=U

# 操作の種類に応じた両側のコミット履歴
# merge の場合：
git log --oneline HEAD...MERGE_HEAD -- <conflicted-files>
# rebase の場合：
git log --oneline REBASE_HEAD~1..REBASE_HEAD -- <conflicted-files>
```

以下を人間に提示する：

1. **操作の種類** — merge / rebase / cherry-pick / stash pop
2. **コンフリクトファイル数と一覧** — 多い場合はカテゴリ分け（src, test, config 等）
3. **推奨する解消順序** — 依存関係がある場合は依存元から。なければ影響が小さいものから
4. **全体の見通し** — 「N件のコンフリクトがあります。順番に見ていきましょう」

### Phase 2: ファイルごとの解消ループ

各コンフリクトファイルに対して以下のサイクルを回す。

#### Step 1: 変更の経緯を調査する

```bash
# 両方のブランチでこのファイルに何があったかを調べる
git log --oneline --all -- <file>
git log -p MERGE_HEAD -- <file>   # 相手側の変更履歴
git log -p HEAD -- <file>         # 自分側の変更履歴
```

コンフリクトの各ハンクについて、**なぜこう変わったか**を突き止める。コミットメッセージ、PR の文脈、周辺コードの変更から意図を読み取る。

#### Step 2: コンフリクトの内容と解消案を提示する

ファイルごと（またはハンクごと — 複雑さに応じてAIが判断）に以下を提示する：

```
## <ファイルパス>（N箇所のコンフリクト）

### ハンク 1（L42-L58）

**ours（現在のブランチ）の変更：**
- コミット abc1234「feat: ユーザー認証にJWT追加」で認証ロジックを変更
- 意図：セッションベースからJWTベースに移行するため

**theirs（マージ元ブランチ）の変更：**
- コミット def5678「fix: セッションタイムアウトの修正」でタイムアウト処理を修正
- 意図：セッション切れ時のエラーハンドリング改善

**解消案：**
JWT移行が進んでいるため、ours側のJWTロジックをベースにしつつ、
theirs側のエラーハンドリングの考え方（タイムアウト時のグレースフル処理）を
JWT版に移植するのが妥当です。

具体的には：
- L42-50: ours を採用（JWT認証ロジック）
- L51-58: 両方を統合（JWTの期限切れハンドリングにtheirsのグレースフル処理を組み込む）
```

**相互機能保持の明示（必須）：**

解消案を出すとき、両側がそれぞれ別の機能・分岐・ロジックを足しているなら **統合・移植を第一案**にする。`ours採用` / `theirs採用`（片側を丸ごと捨てる案）を出してよいのは、捨てる側が「純粋なリネーム / フォーマット / 空白・コメントのみ / 採用側の部分集合」で固有機能が無いと言える時だけ。

片側採用を提案する場合は、**「この案を採ると theirs（または ours）の機能 X が失われます」と必ず明示**してから人間に判断を委ねる。マーカーが消えること自体を解消の根拠にしない。意図が履歴から読み取れず統合の可否が判断できない時は、「どちらの機能を優先すべきか」を率直に尋ねる。

**粒度の判断基準：**

- **ファイル単位で提示** — コンフリクトが1-2箇所で文脈が明確な場合、または機械的に片側を採用すれば済む場合
- **ハンク単位で提示** — コンフリクトが3箇所以上ある場合、両側の変更を統合する必要がある場合、ビジネスロジックに関わる判断が必要な場合

#### Step 3: 人間の承認を待つ

解消案を提示したら、以下の選択肢を提示する：

1. **この案で進める** — AIが提示した解消案を適用
2. **修正して進める** — 人間が方針を指示し、AIがそれに従って修正
3. **自分で直す** — 人間がIDEで直接編集し、完了を報告
4. **スキップ** — このファイルは後で戻ってくる

**人間が承認するまで、次のファイルに進まない。**

#### Step 4: 解消を適用する

承認された解消案をファイルに適用する（コンフリクトマーカーを除去して解消後のコードに書き換える）。

**この時点ではまだ `git add` しない。** ステージングは全ファイルの解消が終わってからまとめて行う。解消済みファイルとして記録し、次のファイルへ進む。

### Phase 3: 全体確認とステージング

全ファイルの解消が終わったら：

```bash
# 未解消のコンフリクトが残っていないか確認
git diff --name-only --diff-filter=U

# 解消結果の全体像を確認（まだステージング前）
git diff
```

以下を人間に提示する：

1. **解消サマリー** — 各ファイルでどう解消したかの一覧
2. **全体の差分確認** — 人間がIDEのDiffビューで全体を通して確認できるよう促す。この段階で「やっぱりこのファイルの解消を変えたい」という手戻りにも対応する
3. **ステージングの確認** — 「全ファイルをステージングしてよいですか？」と確認し、承認されたらまとめてステージングする：

```bash
git add <resolved-file-1> <resolved-file-2> ...
```

4. **次のアクション** — 操作の種類に応じた選択肢を提示する：
   - `git commit` でマージコミットを作成（merge の場合）
   - `git rebase --continue` で rebase を続行（rebase の場合）
   - `git cherry-pick --continue`（cherry-pick の場合）
   - コミット前にビルド/テストを実行して確認
   - コミットせずに終了（人間が後で手動でコミット）

**履歴優先の2段コミットの提案（merge の場合・推奨提示のみ）：**

merge を確定するとき、後でレビュワーが「どのマーカーをどう解消したか」を辿れるよう、**2段コミット**を選択肢として提案してよい：①マーカー入りのまま `git add` して `git commit --no-verify`（マージコミット）→②解消を書き戻して通常 `git commit`。こうすると `git diff <①>..<②>` が解消内容そのものになる（手順は auto スキルの `references/two-stage-commit.md` 参照）。

ただし pair は人間がコミット方針を決めるモードなので、**2段にするかどうかは人間に委ねる**（通常の1コミットを選んでもよい）。AI が勝手に2段で確定しない。

**AIが勝手にコミット/continue を実行しない。** 人間が明示的に指示した場合のみ実行する。

## 核心ルール

- **解消案は提案であり、決定ではない** — 最終判断は常に人間が行う。AIは「こうすべき」ではなく「こうする理由はこれです」と経緯を説明する
- **相互機能保持** — マーカーを消すことはゴールではない。両側が別々の機能を実装しているなら統合・移植を第一案にし、片側採用を提案する時は「これにより失われる機能」を必ず明示する。マーカーが消えること自体を解消の根拠にしない
- **コミット履歴を根拠にする** — 「こちらが新しいから」ではなく「このコミットでこの意図で変更されたから」と具体的に示す
- **人間の承認なしに次に進まない** — 1ファイル（または1ハンク）ずつ確実に合意を取る
- **自動コミットしない** — 全コンフリクト解消後も、コミット/continue の実行は人間の明示的な指示を待つ
- **わからない時は正直に言う** — コミット履歴からも意図が読み取れない場合は「この変更の意図が履歴から判断できません。どちらの変更を優先すべきか教えてください」と聞く

