agentsclimarketplace

Resolve merge conflicts

Skill stealth-engine/skills/skills/resolve-merge-conflicts

Resolve git merge/rebase conflicts non-destructively — preserving the intent of BOTH sides — and hand off to a human when a conflict can't be resolved safely. Use when a branch or PR has conflicts with its base ('this branch has conflicts that must be resolved', GitHub mergeable=CONFLICTING / mergeStateStatus=DIRTY), when a rebase / merge / cherry-pick / stash / revert stops with conflict markers (<<<<<<< ======= >>>>>>>), when a PR is behind base and needs updating, when syncing a long-lived branch or back-merging a hotfix, or when deciding rebase vs merge. Covers the safe-resolution rules (no blind -X ours/theirs, hunk-by-hunk with diff3, abort/reflog escape hatches, verify-after), the rebase ours/theirs inversion, lockfile/rename/semantic conflicts, and the escalate-when-stuck criteria.From its SKILL.md

Install
npx -y skills add stealth-engine/skills --skill resolve-merge-conflicts

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 8 commands, including `git merge --abort` and 7 more.

SKILL.md

8.0 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it

Resolve merge conflicts (non-destructively)

Resolve git conflicts so that both sides' intent survives, verify the result, and stop and ask a human the moment a safe resolution isn't obvious. The git mechanics are the easy part; the danger is silently dropping someone's work — a blind "take theirs," a clean-looking textual merge that's logically broken, or a force-push over a teammate's commits.

Command recipes live in reference/playbook.md (load on demand). This body is the decision rules.

First: rebase or merge?

You update a feature/PR branch against its base one of two ways. Either is fine — pick by context, not dogma:

git rebase origin/maingit merge origin/main
Historylinear (replays your commits)adds a merge commit
Conflictsmay re-hit the same conflict per replayed commit (turn on rerere)resolve once
Push after--force-with-lease (rewrites your branch)normal push
Best foryour own unshared PR brancha branch others also commit to

In a squash-merge repo (see git-trunk-branch-and-pr-automation) the feature branch's history is flattened at merge anyway, so a merge commit on the branch is harmless — when a rebase keeps re-conflicting, merge instead and resolve once. Never rebase a branch other people are actively committing to.

The non-negotiable safety rules

  1. Never blind-resolve a whole side. -X ours / -X theirs (strategy options) and git checkout --ours/--theirs <file> take one side wholesale and throw the other away silently. They're only correct for files you will regenerate (e.g. lockfiles) or a file that genuinely should be one side entirely — never as a "make the markers go away" shortcut.
  2. Resolve hunk-by-hunk, preserving both intents. A conflict means both sides changed the same region. The correct result is usually neither side verbatim but a combination. Turn on diff3/zdiff3 so you can see the common ancestor and reason about what each side changed from (recipe in the playbook).
  3. Know the rebase ours/theirs inversion. During git merge, ours=your branch, theirs=incoming. During git rebase, it's flipped: ours=the branch you're replaying onto (e.g. main), theirs=your commits. Acting on the wrong one discards exactly the work you meant to keep.
  4. Keep the escape hatch ready. git merge --abort / git rebase --abort / git cherry-pick --abort returns you to a clean pre-conflict state. If unsure, abort and reassess rather than push a half-resolved tree. git reflog + ORIG_HEAD recover from a bad finish.
  5. Force-push only --force-with-lease, only your own PR branch. Plain --force clobbers teammate commits pushed since your last fetch; --with-lease refuses if the remote moved.
  6. Never commit conflict markers. Run git diff --check and git diff --cached --check (staged markers won't show in the unstaged diff after git add), plus a grep for <<<<<<<, before --continue/commit.

The loop

1. UNDERSTAND  → what's conflicting + why (mergeable status, conflict list, diff3)
2. CLASSIFY    → per file: content · rename/delete · lockfile/generated · binary · semantic
3. RESOLVE     → hunk-by-hunk, both intents; regenerate (don't hand-merge) lockfiles
4. VERIFY      → no markers; build + tests; diff sanity (no unrelated lines vanished)
5. CONTINUE    → git add; --continue / commit; push (--force-with-lease if rebased)
        │
        └─ at ANY step, if a safe resolution isn't clear → ABORT or stop → HAND OFF

Conflict types — and how each is resolved

  • Content (same lines changed) → the default: merge both intents by hand.
  • Rename/delete & add/add → decide whether the file should exist and where; don't let one side's deletion silently win. (git status labels these.)
  • Lockfiles (package-lock.json, pnpm-lock.yaml, yarn.lock, Cargo.lock) → do not hand-merge. Take one side, then regenerate from the merged manifest (npm install --package-lock-only / pnpm install --lockfile-only / cargo generate-lockfile / etc.) so the lock matches its resolved manifest (package.json, Cargo.toml, …). This is the legitimate use of "take one side."
  • Generated/build output → regenerate from source, never merge by hand.
  • Binary → you can't merge text; pick a side deliberately or escalate.
  • Semantic → the file merges with zero markers but is logically broken (one side renamed a function the other side calls). Textual success ≠ correctness — only build + tests catch these.

Escalate to a human when…

Hand off (with context) rather than guess when:

  • The conflict is a genuine design clash — both sides deliberately changed the same logic in incompatible ways; only the authors can say which intent wins.
  • It's in code whose intent you can't determine, or in migrations / schema / data files where a wrong merge corrupts state.
  • A lockfile regeneration pulls in unexpected dependency changes.
  • The branch is from a fork / untrusted PR — you can't safely run its checked-out code or push to it (consistent with the fork-safety rule in autonomous-pr-driver). Validate via API; don't resolve locally.
  • A rebase keeps re-conflicting across many commits, or the conflict spans many files beyond what you can verify.

How to hand off: state what files conflict, what you tried, and why you stopped — then leave the branch in a clean (aborted) state, or push the partial resolution to a clearly-labelled branch and ask. Same posture as the PR driver's never-self-merge: when in doubt, a human decides.

Verify (before you call it done)

  • git diff --check → no leftover conflict markers / whitespace errors.
  • Build + run the tests — the only thing that catches semantic conflicts.
  • Diff sanity: compare against both parents; confirm no unrelated lines were dropped during the resolution (the silent-data-loss failure mode).
  • For a rebased PR branch, confirm the final range is what you expect before --force-with-lease (recipe in the playbook).

See also

Sources

What ships with it: 1 file

5.9 KB alongside SKILL.md

reference/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.