You ask Codex to keep working on a long-running branch. It starts, then stops with “merge conflict in src/api/handler.ts.” Or worse: it commits a file containing <<<<<<< HEAD markers still in the source. Or it picks the wrong side wholesale, throwing away the new logic that landed on main last week.
Codex was not trained to be a merge conflict expert. The model can read both sides, but without semantic context — knowing why each side exists — it often guesses. The reliable fix is to keep conflicts away from the agent: rebase before invoking, or have setup.sh rebase automatically, and write an AGENTS.md rule that says “if conflict, stop and report” instead of “pick one.”
Common causes
1. Branch is days behind main, conflicts inevitable
You started a Codex task on a feature/x branch from last Tuesday. Main moved 40 commits since. Anything Codex touches is going to conflict.
How to spot it: git log --oneline origin/main..HEAD shows few commits; git log --oneline HEAD..origin/main shows many. The branch is far behind.
2. Agent never ran rebase before starting
Codex’s setup.sh does npm install but not git rebase origin/main. So the agent starts work on a stale tree, and conflicts surface only when it tries to apply_patch.
How to spot it: Setup logs do not include any rebase / pull. First conflict appears at apply_patch step, not before.
3. Codex committed the conflict markers themselves
The model saw <<<<<<< HEAD ... ======= ... >>>>>>> main, did not recognize them as control markers, treated them as plain text. The PR now has real <<<<<<< lines.
How to spot it: git diff origin/main..HEAD | grep -E '^\+(<<<<<<<|=======|>>>>>>>)' returns matches. The build will also fail.
4. Agent picked one side wholesale
When asked to resolve, Codex took ours or theirs for every conflict without reading. It picked the side that produced the smaller diff or fewer compile errors, not the correct one.
How to spot it: PR drops a feature that landed on main recently, or drops the work the branch was supposed to add. Compare with git log.
5. Merge instead of rebase, then conflicting merges of merges
Codex ran git merge origin/main, hit a conflict, fixed it, then later ran git merge origin/main again because of a new commit on main. History becomes a rats-nest of merge commits, each with their own conflicts.
How to spot it: git log --oneline --graph shows many merge commits. Hard to follow history.
Shortest path to fix
Step 1: Rebase before invoking Codex
Make it your own habit, or wire it into the harness:
git fetch origin
git rebase origin/main
# if conflicts, resolve them in your editor, never in Codex
git push --force-with-lease
# now invoke Codex
A clean rebase before the agent runs eliminates 90% of mid-task conflicts.
Step 2: Add pre-rebase to setup.sh
If your Codex harness supports it, in .codex/setup.sh:
#!/usr/bin/env bash
set -euo pipefail
# Refuse to start if the branch is too far behind main
git fetch origin main --quiet
behind=$(git rev-list --count HEAD..origin/main)
if [ "$behind" -gt 50 ]; then
echo "ERROR: branch is $behind commits behind main. Rebase before invoking Codex."
exit 1
fi
# Attempt clean rebase. If conflicts, bail.
if ! git rebase origin/main; then
git rebase --abort
echo "ERROR: rebase produced conflicts. Resolve manually before retrying."
exit 1
fi
npm ci
Now the agent only ever runs on a clean tree. Conflicts surface to a human.
Step 3: AGENTS.md “stop on conflict” rule
## Merge conflict policy
If you encounter merge conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`),
or `git status` shows files in "both modified" state:
1. Stop immediately.
2. Do not edit the file to remove the markers.
3. Do not pick `ours` or `theirs` without explicit human instruction.
4. Run `git rebase --abort` or `git merge --abort` to restore a clean state.
5. Write a note in the PR description listing the conflicting files and
which commits introduced them.
6. Mark the task as blocked.
Never commit a file containing `<<<<<<<`, `=======`, or `>>>>>>>` lines.
The agent now has a clear escape hatch instead of guessing.
Step 4: Pre-commit hook to block conflict markers
In .codex/setup.sh:
mkdir -p .git/hooks
cat > .git/hooks/pre-commit <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
if git diff --cached -U0 | grep -E '^(\+|-)?\s*(<<<<<<<|=======|>>>>>>>)\s' >/dev/null; then
echo "ERROR: commit contains merge conflict markers. Resolve before committing."
exit 1
fi
EOF
chmod +x .git/hooks/pre-commit
Even if the agent ignores the AGENTS.md rule, the commit hook stops it.
Step 5: Manual rebase the night before a big agent run
For multi-step Codex plans (4–5 PRs in sequence), rebase the branch the evening before. Walking into a clean tree saves hours of conflict triage.
# Day before
git fetch origin
git checkout feature/x
git rebase origin/main
git push --force-with-lease
# Verify CI is green on the rebased branch
# Then schedule the Codex run for the morning
Pair with branch protection so force-with-lease is the only force option allowed.
Step 6: Prefer rebase over merge
In AGENTS.md:
When integrating with main, always use `git rebase origin/main`, never
`git merge origin/main`. Do not run rebase yourself — only run it inside
`.codex/setup.sh` at task start. If main moves during your task, do not
re-merge; stop and report.
Rebase keeps history linear. Merge inside a long task produces conflicts of conflicts.
Prevention
- Rebase branches before invoking Codex; bail in setup.sh if too far behind
- AGENTS.md “stop on conflict, never commit markers, never pick sides” rule
- Pre-commit hook blocks any commit containing
<<<<<<</=======/>>>>>>> - Prefer rebase over merge; one rebase point at task start, never mid-task
- For long Codex plans, rebase the night before so the agent walks into a clean tree
- Branch protection so the agent cannot force-push over teammate work mid-conflict