Resolve conflicts
A conflict is two intents meeting. Resolve it by finding out what each side wanted, never by taking
whichever half looks tidier.
The loop
See the state. git status, git log --oneline --left-right --merge, and the conflicting files.
Know whether you are mid-merge or mid-rebase — the finish differs.
Find the primary source for each side. Read the commit messages, and where a side came from a
feature branch, its spec and its review thread. Understand why the change was made before touching
a hunk.
Resolve each hunk. Preserve both intents where you can. Where they are genuinely incompatible, take
the one matching the stated goal of the merge and say what the trade-off was in your report.
Never invent new behaviour in a conflict resolution — it arrives in a diff nobody reviewed against
a spec, which is the least visible place in the whole flow to add something.
Never --abort. Always resolve. An abort loses the analysis you just did and the next attempt
starts cold.
Run the gates, and fix whatever the merge broke rather than whatever you notice.
Finish it. Stage everything and commit; if rebasing, continue until every commit is replayed.
The three that are not a judgement call
.agents/gates.md names the first two for this repo. All three conflict for structural reasons:
- A generated file. Never hand-merge it. Take either side, re-run the command that generates it, and
commit what it writes.
- An append-heavy manifest — a public-API list, an index, a changelog. The resolution is almost always
keep both lines, in the order the file already uses.
- A lockfile. Regenerated, not merged. Take one side, run the install command, commit the result.
Then
Run the gates the way CI runs them, before you claim anything passes. They are recorded in
.agents/gates.md, at the repository root — the commands, their order, and which of them a local run
weakens. Read that file; do not reconstruct the gate from what you see in the tree.
- Run them in the order given. A formatter after a build check wastes the check, and most orders are
written down because somebody already lost an hour to the other one.
- A local command that is not the CI command is not the gate. Where
.agents/gates.md says a local
invocation is softer than CI's — warnings not fatal, a subset of projects, coverage not measured — run
the CI form or say which one you ran.
- Generated files are built once, at integration.
.agents/gates.md names them. Never regenerate one
inside a per-ticket worktree; every parallel tree would rewrite the same file.
- A gate that fails for a reason outside this change is not yours to work around. Say so and stop.
- When a gate fails in a way that makes no sense, read the troubleshooting document
.agents/gates.md points at before debugging your own code.
If .agents/gates.md is missing, run the repo's obvious test and build commands, say which you chose
and that they were not configured, and do not claim CI parity.
If you have not run the command in this message, you cannot say it passes.
Before any statement that work is done, fixed, passing or ready:
- Name the command that would prove the claim.
- Run it in full. Not a subset, not a remembered earlier run.
- Read the whole output and the exit code.
- State the claim with the evidence, or state what actually happened.
| Claim |
What proves it |
What does not |
| tests pass |
the test command's output, 0 failures |
a previous run, "should pass" |
| build succeeds |
exit 0 from the build |
the linter passing |
| lint clean |
the linter's output, 0 errors |
a partial check |
| the bug is fixed |
the original symptom, retested |
the code changed |
| the agent finished |
git diff / git log in its tree |
the agent reporting success |
| the requirement is met |
that requirement checked by name |
the suite being green |
Report what happened, not what you hoped. A failing gate is reported with its output. A skipped step
is reported as skipped. Words that imply success without evidence — "should", "probably", "looks
right" — are the same violation as claiming it outright.
Report which hunks you resolved against which intent, and name every trade-off you took. A conflict
resolved silently is a decision nobody can find later.
1---2name: resolve-conflicts3description: Resolve an in-progress git merge or rebase conflict by finding out why each side made its change, rather than by picking a side. Use when a merge or rebase has stopped with conflicts, when a review reports a merge conflict, or when someone says "fix the conflicts", "this won't merge". Keywords - merge conflict, rebase conflict, conflicts, won't merge, resolve conflicts, both modified, HEAD marker.4---56# Resolve conflicts78A conflict is two intents meeting. Resolve it by finding out what each side wanted, never by taking9whichever half looks tidier.1011## The loop12131. **See the state.** `git status`, `git log --oneline --left-right --merge`, and the conflicting files.14 Know whether you are mid-merge or mid-rebase — the finish differs.15162. **Find the primary source for each side.** Read the commit messages, and where a side came from a17 feature branch, its spec and its review thread. **Understand why the change was made** before touching18 a hunk.19203. **Resolve each hunk. Preserve both intents where you can.** Where they are genuinely incompatible, take21 the one matching the stated goal of the merge and **say what the trade-off was** in your report.22 **Never invent new behaviour** in a conflict resolution — it arrives in a diff nobody reviewed against23 a spec, which is the least visible place in the whole flow to add something.24254. **Never `--abort`.** Always resolve. An abort loses the analysis you just did and the next attempt26 starts cold.27285. **Run the gates**, and fix whatever the merge broke rather than whatever you notice.29306. **Finish it.** Stage everything and commit; if rebasing, continue until every commit is replayed.3132## The three that are not a judgement call3334`.agents/gates.md` names the first two for this repo. All three conflict for structural reasons:3536- **A generated file.** Never hand-merge it. Take either side, re-run the command that generates it, and37 commit what it writes.38- **An append-heavy manifest** — a public-API list, an index, a changelog. The resolution is almost always39 **keep both lines**, in the order the file already uses.40- **A lockfile.** Regenerated, not merged. Take one side, run the install command, commit the result.4142## Then4344<!-- shared:gates:start source=gates.md -->45**Run the gates the way CI runs them, before you claim anything passes.** They are recorded in46`.agents/gates.md`, at the repository root — the commands, their order, and which of them a local run47weakens. Read that file; do not reconstruct the gate from what you see in the tree.4849- **Run them in the order given.** A formatter after a build check wastes the check, and most orders are50 written down because somebody already lost an hour to the other one.51- **A local command that is not the CI command is not the gate.** Where `.agents/gates.md` says a local52 invocation is softer than CI's — warnings not fatal, a subset of projects, coverage not measured — run53 the CI form or say which one you ran.54- **Generated files are built once, at integration.** `.agents/gates.md` names them. Never regenerate one55 inside a per-ticket worktree; every parallel tree would rewrite the same file.56- **A gate that fails for a reason outside this change is not yours to work around.** Say so and stop.57- **When a gate fails in a way that makes no sense**, read the troubleshooting document58 `.agents/gates.md` points at before debugging your own code.5960If `.agents/gates.md` is missing, run the repo's obvious test and build commands, **say which you chose61and that they were not configured**, and do not claim CI parity.62<!-- shared:gates:end -->6364<!-- shared:evidence-before-claims:start source=evidence-before-claims.md -->65**If you have not run the command in this message, you cannot say it passes.**6667Before any statement that work is done, fixed, passing or ready:68691. Name the command that would prove the claim.702. Run it in full. Not a subset, not a remembered earlier run.713. Read the whole output and the exit code.724. State the claim **with** the evidence, or state what actually happened.7374| Claim | What proves it | What does not |75|---|---|---|76| tests pass | the test command's output, 0 failures | a previous run, "should pass" |77| build succeeds | exit 0 from the build | the linter passing |78| lint clean | the linter's output, 0 errors | a partial check |79| the bug is fixed | the original symptom, retested | the code changed |80| the agent finished | `git diff` / `git log` in its tree | the agent reporting success |81| the requirement is met | that requirement checked by name | the suite being green |8283**Report what happened, not what you hoped.** A failing gate is reported with its output. A skipped step84is reported as skipped. Words that imply success without evidence — "should", "probably", "looks85right" — are the same violation as claiming it outright.86<!-- shared:evidence-before-claims:end -->8788**Report which hunks you resolved against which intent**, and name every trade-off you took. A conflict89resolved silently is a decision nobody can find later.