Merge Conflict Resolution skill for Codex
Keep both intents, not just one side's text. Codex resolves conflicts by reading why each side changed the code, using zdiff3 to see the common base and keeping the rebase ours/theirs inversion straight. Lockfiles, codegen output, snapshots and parallel migrations are regenerated with the right tool rather than spliced, rerere handles repeat conflicts, and every merge is built and tested because clean merges can still be broken.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- merge-conflict-resolution Installs to ~/.agents/skills/merge-conflict-resolution/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install merge-conflict-resolution The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project merge-conflict-resolution Installs to .agents/skills/merge-conflict-resolution/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/merge-conflict-resolution.zipunzip -o merge-conflict-resolution.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) merge-conflict-resolution PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $merge-conflict-resolution, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Resolves git merge, rebase and cherry-pick conflicts by intent rather than by picking a side - reading base, ours and theirs with zdiff3, handling the ours/theirs inversion during rebase, regenerating lockfiles (npm, pnpm, Yarn, uv, Poetry, Go, Cargo) and generated files instead of hand-merging them, merging parallel migrations, reusing resolutions with rerere, and catching semantic conflicts that produce no markers. Use when a merge or rebase stops with conflicts, a lockfile or snapshot conflicts, or a merge compiled but broke behaviour.
Use it when
- A merge, rebase or cherry-pick stops with conflicts
- Lockfiles, snapshots or generated code conflict
- A clean merge compiles but behaviour broke
Use something else when
- You want to restructure commits rather than combine branches: use git-history-surgery
- The failure predates the merge and you need the commit that caused it: use git-bisect
How to check the result
No conflict markers remain, the lockfile diff touches only expected packages, and build, types and tests pass on the merged result.
The mistake it prevents
Taking --theirs during a rebase believing it means the main branch, when in a rebase theirs is your own commit being replayed.
A conflict is resolved when the result contains the intent of both sides, not just the text of one, the project builds and its tests pass on the merged result, no conflict markers remain, and generated files were regenerated rather than spliced by hand.
First, look before editing
git status # which operation is in progress
git diff --name-only --diff-filter=U # conflicted paths
git config merge.conflictStyle zdiff3 # show the common base inside markers (Git 2.35+)
git checkout --conflict=zdiff3 -- <path> # re-render an existing conflict with the base
Understand why each side changed the code before choosing:
git log --merge --oneline -- <path> # commits from both sides touching the path
git show :1:<path> > "$TMPDIR/base" # common ancestor
git show :2:<path> > "$TMPDIR/ours" # stage 2
git show :3:<path> > "$TMPDIR/theirs" # stage 3
git log -1 --format=%B <sha> # read the commit message for intent
Which side is “ours”
| Operation | ours / stage 2 | theirs / stage 3 |
|---|---|---|
git merge feature (on main) | main, the branch you are on | feature, being merged in |
git rebase main (on feature) | main plus already-replayed commits | your feature commit being replayed |
git cherry-pick <sha> | current branch | the picked commit |
The rebase inversion causes most wrong resolutions. Say out loud which side is yours
before using --ours or --theirs.
Resolve by conflict type
| Pattern in the hunk | Resolution |
|---|---|
| Both sides added different lines at the same spot (imports, list entries, routes) | Keep both; order them by the file’s convention; remove duplicates |
| One side changed logic, the other reformatted or renamed | Take the structural change, then re-apply the logic change by hand |
| One side moved or extracted code, the other edited it in the old place | Apply the edit to the code’s new location; delete the old copy |
| Same line changed differently for different reasons | Combine both intents; if incompatible, ask the user which wins |
| Modify/delete (one side deleted the file) | Find out why it was deleted; usually port the modification to wherever the code went |
| Both sides fixed the same bug differently | Keep one fix, not both; prefer the one with a test |
Edit the file to the final intended content, remove every marker, then:
git add <path>
rg -n '^(<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|)( |$)' . # no markers anywhere
git diff --cached --check # also flags leftover markers
Files you regenerate, never hand-merge
Lockfiles
Resolve the manifest (package.json, pyproject.toml, go.mod, Cargo.toml) first,
then let the tool rebuild the lockfile. Most of these need registry access, which may need
network approval in the Codex sandbox.
| Lockfile | Command after the manifest is resolved |
|---|---|
package-lock.json | npm install (npm resolves lockfile conflict markers itself) |
pnpm-lock.yaml | pnpm install (pnpm resolves lockfile conflicts on install) |
yarn.lock (Berry) | yarn install |
uv.lock | uv lock |
poetry.lock | poetry lock (Poetry 1.x: poetry lock --no-update) |
go.sum | keep both sides’ lines, then go mod tidy |
Cargo.lock | git checkout --theirs Cargo.lock (or ours), then cargo metadata >/dev/null to re-sync |
Gemfile.lock | bundle lock |
Do not delete the lockfile and regenerate from scratch; that upgrades every dependency.
Check afterwards that only expected packages changed: git diff --cached --stat.
Other generated output
- Codegen (GraphQL types, protobuf stubs, ORM clients, OpenAPI clients): resolve the
source schema, re-run the generator from
AGENTS.mdorpackage.jsonscripts. - Built assets and minified bundles committed to the repo: rebuild.
- Test snapshots: resolve the code, re-run the tests with the update flag (
-u), and review the snapshot diff like code. - Changelogs: keep both entries in the right section.
Database migrations
Two branches each adding a migration create parallel heads even without a textual conflict:
alembic heads # more than one head means a merge migration is needed
alembic merge heads -m "merge heads"
python manage.py makemigrations --merge # Django
Sequential numbered migrations with the same number: renumber the one that has not been deployed anywhere, after confirming with the user.
Semantic conflicts (no markers, still broken)
Git merges text, not meaning. A clean merge can still break when one side renamed a function and the other added a call to the old name, changed a default the other relies on, or added an enum value the other’s exhaustive switch does not handle. Always run the build, type checker and tests after a merge, even a clean one. Review what the resolution itself introduced:
git show --remerge-diff <merge-sha> # Git 2.36+: how the committed merge differs from git's automatic attempt
Continue, abort, repeat
GIT_EDITOR=true git rebase --continue # non-interactive: keeps the original message
git commit --no-edit # finish a merge with the default message
git cherry-pick --continue
git merge --abort # back to the start (or rebase/cherry-pick --abort)
For long rebases that hit the same conflict repeatedly, enable rerere so git records and replays resolutions:
git config rerere.enabled true
git rerere diff # what rerere recorded for the current conflicts
git rerere forget <path> # drop a wrong recorded resolution
rerere replays silently; review its auto-resolved files before continuing, and forget any resolution you later find wrong.
Hard rules
- Never resolve a whole conflicted file wholesale with
--ours/--theirsunless you have confirmed the other side’s changes are fully obsolete. - Never commit with markers; never use
git add .to mark everything resolved without checking each file. - Do not force-push the result of a rebase on a shared branch without the user’s
confirmation (
--force-with-lease --force-if-includesonly). - If both intents cannot be combined, stop and ask the user. Do not silently drop one.
Verification
- No conflict markers: the
rgsearch above returns nothing. - Build, type check and full test suite pass on the merged result.
- Lockfile diff contains only expected packages.
- For each conflicted file,
git diff <ours-ref> -- <path>andgit diff <theirs-ref> -- <path>show that each side’s change survived.
Report
Resolved 5 conflicts rebasing feature/bulk-pricing onto origin/main:
src/cart.py main extracted tier logic to tiers.py; re-applied our single-tier cap there
src/routes.ts both added routes; kept both, sorted
package-lock.json regenerated with npm install after resolving package.json
tests/__snapshots__ re-recorded; 1 snapshot changed (new route in sitemap)
migrations/ added alembic merge revision 7c1e2f
Checks: build OK, tsc clean, 512 tests passed. Not pushed. What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Merge Conflict Resolution"
short_description: "Keep both intents, not just one side's text"
default_prompt: "$merge-conflict-resolution My rebase onto main stopped with conflicts in five files, resolve them properly" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.