agentleFS
ohyesgocoolohyesgocool/feature-loop/skills/resolve-conflicts/SKILL.md

resolve-conflicts

Skill0 starsChanged 4 months agoMITView on GitHub

Integrate a moved target branch into a feature branch and resolve the conflicts — safely enough to run unattended. Merges the target in rather than rebasing, so the MR's existing review threads stay anchored and nothing needs a force-push. Classifies every conflicted file before touching it: lockfiles and generated artifacts are regenerated rather than hand-merged, migrations are renumbered rather than merged, additive lists are unioned, and logic conflicts are resolved by reading both sides' intent — never by picking a side. Then it proves the integration: no surviving markers, every hunk the target contributed still present in HEAD (the "took ours wholesale" check), full gates green, and the feature re-verified. Hard stops are the point: same-migration edits, unresolvable lockfiles, binaries, delete/rename conflicts, oversized conflict sets, and genuine guesswork all stop with the tree exactly as it was and a rollback anchor printed. Use when: an MR shows conflicts with its target, "resolve the conflicts", "main moved and my branch won't merge", or as the merge gate's conflict stage under /ship-feature.

  • Deletes or force-pushes
  • Commits and pushes

16 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use worktree, worktrees and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • MicrosoftSkill

    worktree

    Create, reuse or clean up a dedicated git worktree for working on a pull request or a private branch. Use from any PR-scoped workflow that needs an isolated checkout to keep current code and build output untouched.

    Also in 5 projects that use this

  • nilecuiSkill

    worktrees

    Guide for using git worktrees to parallelize development with coding agents. Use this skill when the user requests to work in a new worktree or wants to work on a separate feature in isolation (e.g., "Work in a new worktree", "Create a worktree for feature X").

    Also in 3 projects that use this

  • johnlindquistSkill

    diagram

    Maintain and synchronize Unified Impact Diagrams following Diagram Driven Development (DDD) methodology. Create, update, and manage diagrams that connect user value to technical implementation.

    Also in 3 projects that use this

  • nicolasestremSkill

    document

    Create focused documentation for specific components or features

    Also in 3 projects that use this

  • AWSSkill

    wizard

    Generate an interactive bash wizard that walks a human through steps only they can perform. Use when provisioning infrastructure, setting up credentials or CI secrets, walking an unfamiliar third-party dashboard, or running a one-off migration or cutover. Don't invoke this for steps the agent can perform itself.

    Also in 4 projects that use this

  • sunnyclinches44Skill

    explain

    Explains code using real-world analogies and ASCII diagrams

    Also in 4 projects that use this

The file

We split this skill into the rules it gives an agent

3 rules. 0 are common, 3 are distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 16 edited versions we read keep these.

  • 3

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every hard stop leaves the tree exactly as it was — git merge --abort — and reports the anchor sha plus what a human needs to decide:

    line 177
  2. Distinctive:

    Classify before resolving: Not every conflict is a text merge.

    line 199
  3. Distinctive:

    Report the rollback: Every run ends with the exact command that undoes it.

    line 208

“Common” is measured: kept by at least 6 in 10 of the 16 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Resolve Conflicts

The target branch moved and the MR won't merge. Integrate the target into the feature branch, resolve what conflicts, and prove the result — then let the caller merge.

/ship-feature calls this unconditionally from its merge gate, so the no-conflict path must be free: probe, find nothing, exit without creating a commit.

Forge note. Written for GitLab (glab). On GitHub: gh pr view <n> --json mergeable,mergeStateStatus,baseRefName for the conflict state, gh pr view <n> --json url for the link. The git work is identical.


Strategy: merge the target in. Not rebase.

This matters enough to state the reasoning, so nobody "optimizes" it back:

  1. Review threads are anchored to commits. GitLab positions diff notes against (base_sha, start_sha, head_sha). A rebase rewrites every commit, so after the force-push GitLab re-maps what it can and marks the rest outdated — those threads fall out of the diff view. In this loop that means /address-review's own replies detach from the code they cite, and /ship-feature's convergence check ("every thread replied to") starts reading a mangled thread set.
  2. /mr-review's delta mode depends on sha ancestry. It reads the Reviewed: <sha> footer and diffs from there. After a rebase that sha is no longer an ancestor of head, so the round silently falls back to a full review — correct, but it doubles reviewer cost for the rest of the loop.
  3. A bad merge is undoable; a bad force-push is archaeology. git revert -m 1 <merge-sha> versus reflog spelunking on a machine that may not be yours.

Rebase only when both hold: the MR has zero discussions (nothing to orphan) and the project enforces linear history — glab api "projects/:id" | jq -r .merge_method returns ff or rebase_merge. Then prefer the server-side glab mr rebase <iid>, which refuses on conflict instead of leaving you in a rewrite, and only fall back to a local git rebase origin/<target> plus git push --force-with-lease if that can't proceed. Never force-push while a review round is in flight. Whichever strategy ran is named in the report.


Process

Step 0: Preconditions

  1. Resolve the MR ($ARGUMENTS, else glab mr list --source-branch "$(git branch --show-current)") and its target_branch.
  2. git status --porcelain must be empty. Dirty tree → stop; another session may own this checkout, and stashing someone else's work is not yours to do.
  3. Record the rollback anchor — git rev-parse HEAD — and print it. Every hard stop below reports it.
  4. git fetch origin <target> --quiet.

Step 1: Probe — calling this skill must be free

git merge --no-commit --no-ff origin/<target>

Clean? git merge --abort, report "no conflicts — target integrates cleanly", exit. Do not leave an empty merge commit behind; a merge gate that calls this every round must not add a commit every round.

Conflicts? Keep the merge in progress and continue.

Step 2: Classify before you resolve

git diff --name-only --diff-filter=U      # both-modified
git ls-files -u                            # full unmerged index, with stages
git status --porcelain                     # DU / UD / AA / DD / AU / UA codes

Only UU (both-modified) in ordinary source is eligible for automatic resolution. Print the classification table before touching a file — a reader of your report must be able to see what you decided before seeing what you did.

Step 3: Resolve, per class

ClassRule
Lockfiles & generated — package-lock.json, pnpm-lock.yaml, yarn.lock, poetry.lock, Pipfile.lock, Cargo.lock, go.sum, Gemfile.lock, composer.lock, *.pb.go, *_pb2.py, generated OpenAPI/GraphQL schemas, snapshots, built assetsNever hand-merge a hunk. Take the target's version (git checkout --theirs -- <file> — during a merge --ours is your branch, --theirs is the incoming target), then regenerate with the project's own command (npm install, poetry lock --no-update, make generate, buf generate, the snapshot updater) and stage the regenerated artifact. If you cannot identify the regeneration command from the repo, or it fails → hard stop. A hand-merged lockfile is a supply-chain incident waiting to happen.
Migrations — numbered or timestamped schema filesTwo different new migrations landing on both sides is a renumber, not a merge: keep both files, and if the project uses a numeric sequence and the numbers collide, rename ours to the next free number and grep for every reference to the old name. If both sides edited the same migration file, or the target's migration touches the same table or column as ours → hard stop. Wrong migration order is the one class of mistake that isn't recoverable in production.
Additive lists — import blocks, __init__.py exports, barrel files, requirements.txt, DI registries, route tables, i18n key files, CHANGELOG.mdUnion merge: keep both sides' entries, dedupe, re-sort in the file's existing order (alphabetical, or grouped stdlib/third-party/local — match what the file already does). Mechanically safe because the entries are independent. Confirmed by the type checker afterwards, not by eye.
Logic conflicts — both sides changed the same linesDo not pick a side. Read both versions and the target commit that introduced its change (git log -1 --format='%s%n%b' <sha> -- <file>, git log -L <start>,<end>:<file>) to recover both intents, then write the version that satisfies both. Record the reasoning per file. The dangerous part is outside the hunk: if the target renamed a symbol, changed a signature, or altered a contract your branch depends on, the conflict markers only show the tip — grep the whole branch for the old name before calling it resolved.
Delete/modify, rename conflicts (DU, UD, AA, DD, AU, UA)Hard stop. Never silently resurrect a deleted file and never silently drop your change. If the target deleted a file your branch edits, the functionality usually moved — say where you think it went, and let a human confirm.
Binary filesHard stop, unless exactly one side changed it and the other only moved it.
Any resolution that deletes a test, an assertion, or a validation check present on either sideHard stop. That is how a conflict resolution quietly removes coverage.

Step 4: Verify the integration — all of it, in order

a. No markers survive.

git diff --check
grep -rnE '^(<<<<<<<|=======|>>>>>>>)' -- <the files you touched>

b. The target-work check — the one that matters most. The classic bad auto-resolution is "took ours" wholesale, silently reverting somebody else's commit. Green tests will not catch it; the reverted work simply disappears. For every file the target changed since the merge base, confirm the target's change is still present in HEAD:

base=$(git merge-base HEAD origin/<target>)
git diff --name-only $base origin/<target> | while read -r f; do
  git diff $base origin/<target> -- "$f"   # what the target contributed
  git diff HEAD -- "$f"                     # what survived
done

Any target hunk missing from HEAD without a deliberate, recorded reason → hard stop.

c. Semantic collisions git never flagged. A clean git status is not evidence of a correct integration. Two branches adding different files never conflict textually, and that is exactly how a broken deploy gets built. Scan the merged result for:

  • duplicate migration sequence numbers or migration ids across the combined set
  • duplicate route paths, duplicate enum values, duplicate registry/DI keys introduced by the two sides
  • a file your branch modified that the target deleted or renamed
  • changes to CI config, deploy manifests, or dependency manifests on either side

Any hit → hard stop, named.

d. Full gates, unpiped, to a log file, greppable after: type checker, full test suite, and the production build where the project has one.

e. Feature re-verify. Re-run the tests covering the plan's success criteria — or the REQs, on a ticket-driven run. A green suite proves nothing broke; it does not prove the feature still works.

f. Only then commit and push. git commit --no-edit (or chore: merge origin/<target> into <branch>) and a plain git push. Never --force on the merge path.

Step 5: Report

## Conflict Resolution — {branch} ← origin/{target}

Strategy: merge ({n} discussions preserved) | rebase (no discussions, linear-history project)
Anchor before resolution: {sha}
Rollback: git revert -m 1 {merge-sha}   [or git reset --hard {sha} if not yet pushed]

Conflicts: {n} files
  logic     {file} — {both intents, and the version written}
  generated {file} — took target, regenerated with `{cmd}`
  additive  {file} — union of {a}+{b} entries, deduped, re-sorted
  migration {file} — renumbered 047 → 049; 3 references updated

Verification: markers ✅ · target-work check ✅ ({k} target hunks confirmed present) ·
  semantic scan ✅ · type-check ✅ · tests ✅ ({n}) · build ✅ · feature re-verify ✅

Hard stops

Every hard stop leaves the tree exactly as it was — git merge --abort — and reports the anchor sha plus what a human needs to decide:

  • Any class marked hard-stop above: unknown or failing lockfile regeneration, both sides editing one migration, delete/rename conflicts, binaries, a resolution that would drop a test.
  • Gates still red after resolution and not fixable within this skill's scope.
  • Size guard: more than 20 conflicted files, or roughly 400 conflicted lines. That is a "rebase the feature" conversation, not an auto-resolve.
  • Moving target: git fetch shows the target advanced again mid-resolution → re-run once; twice in a row → stop, the target needs a quiet window.
  • Genuine guesswork: two plausible readings of intent with no evidence to choose between them. Name both readings, then stop. Guessing here produces code that compiles, passes, and is wrong.

Rules

  • Merge in, don't rebase — unless the MR has no discussions and the project requires linear history. Review threads and delta reviews both depend on the existing shas.
  • Never force-push mid-review. Rebasing is a stage-boundary action, never something that happens while a review round is in flight. After any force-push: record the pre-rebase sha and post it as an MR comment, clear the recorded reviewed_sha so the next round is a full review, and re-run the full gate before believing anything.
  • Classify before resolving. Not every conflict is a text merge. The file's kind decides the method, and three kinds have no safe automatic method at all.
  • Never pick a side to make it compile. --ours / --theirs wholesale on a logic conflict is the failure this skill exists to prevent, and the target-work check is what catches it.
  • A clean git status is not a correct integration. The conflicts git flags are the easy ones; run the semantic scan.
  • Stops are cheap, wrong merges are not. Aborting costs a human ten minutes. A silently reverted commit or a mis-ordered migration costs a production incident and nobody knows where it came from.
  • Report the rollback. Every run ends with the exact command that undoes it.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.