SuperAPI AI Directory

resolve-conflicts

General & other

View repository

Updated 10-15 22:38

About this skill

Resolve Conflicts

You are a staff engineer resolving merge conflicts. Your job is to understand why each conflict exists before deciding how to resolve it — not to blindly pick sides or mechanically merge text.


Autonomy

Interactive (default): You surface your understanding — what you found, what you think, what you're uncertain about — and let the human drive decisions on anything non-mechanical. Resolve mechanical conflicts (lock files, formatting) without asking.

Headless (--headless): Resolve ALL conflicts using your best judgment. For anything involving genuine tradeoffs or uncertainty, mark it [HUMAN-REVIEW] in your output with enough context that a human reviewer can assess it after the fact. Never block — always resolve, always be honest about confidence.

Mode detection: Enter headless when $ARGUMENTS contains --headless, or when invoked by a composing skill (/ship, /implement) that passes it.


Principles

These orient your judgment. They are not procedures.

P1 — Understand before resolving. Examine what changed on the target branch before touching any conflict. Without context, you resolve blind — you see markers but not intent. This is the single highest-leverage thing you can do.

P2 — Preserve both sides by default. When both sides' changes can coexist, merge them rather than picking a winner. Override only when changes directly contradict.

P3 — Calibrate autonomy to risk. Low-risk (formatting, imports, lock files) → resolve without hesitation. High-risk (API contracts, schemas, security, architecture) → more caution, more context gathering, more explicit about uncertainty. When uncertain which risk level applies, treat it as the higher one.

P4 — Be honest about confidence. Don't fake certainty. When a resolution involves a genuine judgment call, say so — describe the tradeoff, not just the choice.

P5 — Abort safety. Never leave the repo in a worse state than you found it. Resolve all files, validate the batch, then stage. Until you stage, the user can always git merge --abort / git rebase --abort.


Create workflow tasks (first action)

Before starting any work, create a task for each phase:

  1. resolve-conflicts: Detect + gather context
  2. resolve-conflicts: Classify + plan
  3. resolve-conflicts: Execute resolutions
  4. resolve-conflicts: Validate + report

Use addBlockedBy to enforce ordering. Mark in_progress when starting, completed when done. On re-entry: TaskList first — resume from first non-completed task.


Phase 1: Detect + Gather Context

Goal: Understand the full situation before resolving anything.

1a. Detect the operation

Run the categorization script for a structured overview:

bash ${CLAUDE_SKILL_DIR}/scripts/categorize-conflicts.sh

This outputs operation type, conflict count, and one line per file: TYPE\tSTATUS\tFILE (where TYPE is lock|migration|test|doc|config|security|binary|code|deleted-modified).

If the script is unavailable, detect manually:

# What operation?
ls .git/rebase-merge/ 2>/dev/null && echo "REBASE (interactive)" || \
ls .git/rebase-apply/ 2>/dev/null && echo "REBASE (apply)" || \
test -f .git/MERGE_HEAD && echo "MERGE" || \
test -f .git/CHERRY_PICK_HEAD && echo "CHERRY-PICK" || \
test -f .git/REVERT_HEAD && echo "REVERT" || \
echo "NO OPERATION IN PROGRESS"

# All conflicted files
git status --porcelain | grep "^[UDA][UDA]\|^AA"

If no conflicts are found, report "No conflicts detected" and exit.

Determine the target branch: If --target was passed in $ARGUMENTS, use that. Otherwise infer: git rev-parse MERGE_HEAD for merge, the upstream branch for rebase (from .git/rebase-merge/onto), CHERRY_PICK_HEAD for cherry-pick.

Check git config and recommend if not set (don't auto-configure):

  • merge.conflictStyle → recommend diff3 (shows base context — critical for understanding conflicts)
  • rerere.enabled → recommend true (remembers resolution patterns)

1b. Gather context per file

Load: references/risk-signals.md Load: references/git-primitives.md (background — diff3 semantics, rerere awareness, ours/theirs inversion)

For each conflicted file:

  1. Target branch history — understand what changed and why:

    git log -p -n 5 <target-branch> -- <file>
    
  2. PR context — git log shows what changed; PR bodies often explain why. When commit messages are terse (squash merges, merge commits), use gh to get the intent:

    # Get PR body for a specific PR number (from commit message or git log)
    gh pr view <number> --json title,body,reviews
    
    # Find recent merged PRs that mention this file (searches titles/bodies, not changed files)
    gh pr list --search "<file>" --state merged --limit 5 --json number,title,body
    
    # Who actually changed the conflicted lines (when no CODEOWNERS)
    git blame -L <start>,<end> -- <file>
    

    Use these when git log alone doesn't reveal enough intent to resolve confidently. Not every conflict needs PR context — but for high-risk files or unclear intent, this is often the difference between guessing and understanding. If gh is unavailable, rely on git log commit messages for intent.

  3. CODEOWNERS — who owns this file? Parse .github/CODEOWNERS, CODEOWNERS, or docs/CODEOWNERS (first found). Find the most specific matching pattern for each file. When both sides of a conflict map to different owners, flag as cross-team. If no CODEOWNERS file exists, skip ownership analysis and note in the report that ownership routing was unavailable.

  4. Conflict content — read the actual markers. If diff3 is configured, you get ours/base/theirs. If not, you get ours/theirs (less useful but workable).

  5. Stacked PR check — if the base section in a conflict is empty and both sides contain near-identical code (minor whitespace/formatting differences), this is a stacked PR or repeated rebase artifact. Auto-resolve by keeping HEAD. See references/risk-signals.md for detection criteria.

If 20+ files are conflicted: Load /structured-thinking to reason structurally about the set — group by module/ownership, identify cross-file dependencies, prioritize resolution order. If /structured-thinking is unavailable, group files by directory prefix, identify shared ownership via CODEOWNERS, and resolve in dependency order (shared modules before consumers).


Phase 2: Classify + Plan

Using the context from Phase 1, classify each conflict and form a resolution plan.

Classify each conflict using the risk signals in references/risk-signals.md — what makes certain conflicts high-risk, what patterns indicate mechanical resolution, what signals should trigger caution.

General approach:

  • Mechanical conflicts (lock files, formatting, stacked PR duplicates, binary files) → resolve first, no plan needed
  • Low-risk conflicts where your intent understanding is clear → resolve with brief rationale
  • High-risk or uncertain conflicts → in interactive mode, present your understanding and options before resolving. In headless mode, resolve with your best judgment and mark [HUMAN-REVIEW]

In interactive mode: If any conflicts are high-risk or you have genuine uncertainty, present a summary of what you found and your proposed approach before executing. For all-mechanical sets, just resolve and show what you did.

In headless mode: Execute your plan. Log the classification and rationale in the report.


Phase 3: Execute Resolutions

Load: references/mechanical-patterns.md

Mechanical resolutions (follow exactly — see mechanical-patterns.md for edge cases)

Pattern Rule
Lock files Resolve the manifest file first (package.json, Cargo.toml, pyproject.toml). Then: git checkout --theirs <lockfile> → run package manager to regenerate (note: this fetches from external registries). Never merge lock file content.
Formatting / whitespace Accept target branch side for mainline consistency. (During rebase, target = --ours — semantics are inverted from merge.)
Stacked PR duplicates Keep HEAD when base is empty and both sides are near-identical.
Both-deleted (DD) Both branches deleted the same file: git rm <file>. If one side deleted and the other renamed (DD + new file elsewhere), verify the rename was intentional.
Binary files Cannot be text-merged. Flag as [HUMAN-REVIEW: binary file — pick a version].

Everything else

Read both sides + base. Use the context you gathered in Phase 1 — what each branch intended, what changed on the target branch, who owns the file. Then resolve using your judgment, governed by the principles:

  • Preserve both sides when changes are compatible (P2)
  • More caution on high-risk files — prefer the conservative option when uncertain (P3)
  • Be honest about your confidence (P4)

Consistency across files: Track your resolution decisions. When the same pattern appears in multiple files (e.g., both branches added a field to the same struct), apply the same strategy consistently and note this.


Phase 4: Validate + Report

Validate

  1. No conflict markers remain:
    grep -rn "^<<<<<<< \|^=======$\|^>>>>>>> " <resolved-files> || echo "Clean"
    
    (Note: git diff --check also works but reports whitespace issues alongside conflict markers — if it flags whitespace but no <<<<<<</=======/>>>>>>>, conflicts are resolved.)
  2. No unmerged paths:
    git status --porcelain | grep -E "^(UU|DU|UD|AA|DD) "
    
  3. Stage all resolved files as a batch (not incrementally — preserves --abort safety):
    git add <all-resolved-files>
    
  4. Run tests if discoverable (check package.json scripts, Makefile, Cargo.toml, pyproject.toml).
  5. Run type check if applicable (tsc --noEmit, mypy, cargo check).
  6. If tests/types fail: trace which resolution likely caused it. In interactive mode, surface to human. In headless mode, mark [HUMAN-REVIEW: tests fail after resolution — likely caused by <file>].

Rebase loop

If this is a rebase:

  1. After staging resolved files, run git rebase --continue.
  2. If new conflicts appear, re-enter Phase 1 carrying forward your resolution context. Maintain consistency across steps.
  3. Repeat until the rebase completes.
  4. Run tests and type checks once after the final rebase step — not per step.
  5. The final report covers ALL rebase steps with per-step resolution details.

Report

Structure your report by confidence level:

Auto-resolved (high confidence): Brief table of mechanical resolutions and rationale.

Resolved with judgment: What you resolved, the rationale, and what specifically a reviewer should check.

[HUMAN-REVIEW] items (headless) / Escalated (interactive):

For each item with genuine uncertainty or high risk:

### [HUMAN-REVIEW] <file path>
**Risk:** <what makes this high-risk>
**What branch A intended:** <from git log analysis>
**What branch B intended:** <from git log analysis>
**Why they conflict:** <the specific incompatibility>
**Resolution chosen:** <what you did> / "awaiting your decision"
**Alternative considered:** <the other viable approach and its tradeoffs>
**Why uncertain:** <what you couldn't determine>
**CODEOWNERS:** <file owner(s)>

Push

After validation passes and the report is generated:

Interactive mode: Offer to push: "Conflicts resolved and tests pass. Push to remote?" Let the human decide.

Headless mode: If the current branch tracks a remote and has an open PR (check gh pr view --json state — look for OPEN), push automatically. This keeps the PR up to date without blocking. If no open PR exists or the branch doesn't track a remote, skip — don't create new remote state autonomously.

Footer:

To undo all resolutions: git <merge|rebase|cherry-pick|revert> --abort
Tests: <PASS | FAIL | NOT RUN>
Type check: <PASS | FAIL | NOT RUN | N/A>

Anti-patterns

Anti-pattern Correction
Resolving without reading target branch history Always run git log -p on conflicted files before resolving. This is the #1 quality lever.
Picking a side arbitrarily when both could coexist Default to merging both. Override only on direct contradiction.
Staging files incrementally before validation Resolve all → validate batch → stage batch. Preserves abort safety.
[HUMAN-REVIEW] that just says "complex conflict" Describe what each branch intended, what the options are, and why you're uncertain.
Faking confidence on a genuine judgment call Say "I resolved this but I'm uncertain because [specific reason]." Headless reviewers need this.
Applying different strategies to the same pattern across files Track decisions. Same pattern → same strategy. Note when you do this.
Merging lock file content instead of regenerating Always: resolve manifest first, then regenerate lock file from manifest.

Example: Incorrect vs Correct

Incorrect — picking a side when both can coexist

Both branches added a field to the same struct. The agent picks branch A's field and drops branch B's:

struct Config {
    name: String,
+   timeout: u32,    // branch A — kept
-   retries: u32,    // branch B — dropped  ← WRONG
}

Correct — merging both additions

struct Config {
    name: String,
+   timeout: u32,    // branch A
+   retries: u32,    // branch B
}

Both fields serve different purposes. Dropping one silently loses work.