Lesson 5 of 6
Merge in order and resolve conflicts
Merge verified branches in dependency order, resolve src/main.ts by combining intents, re-check after every merge, and undo safely without reset --hard.
Merge in the plan’s order, one branch at a time
Merge in the order the plan declares, not the order workers finished. The interface is already frozen in the recorded baseline. If you made a separate interface branch, merge it first; then one feature branch at a time. Integration last. After each merge, run the checks. When something breaks, exactly one merge caused it.
Work on a dedicated integration branch so the baseline stays clean:
cd ~/agent-lab/task-tracker
git status --short
git checkout -b integrate/multi-agent <baseline-commit>
git merge --no-ff feat/due-dates
npm test && npm run typecheck
--no-ff always creates a merge commit, so each worker’s contribution stays visible and revertible. Do not batch three merges and then debug. Do not merge a branch whose status is still done, unverified.
Read both sides of a conflict — never take ours or theirs as a reflex
src/main.ts is the planned merge point because every feature registers there. After merging tags on top of due, you should expect:
<<<<<<< HEAD
import { dueFeature } from './features/due';
const features = [dueFeature];
=======
import { tagsFeature } from './features/tags';
const features = [tagsFeature];
>>>>>>> feat/tags
Git is not telling you which side is right. Each side dropped the other feature. Re-read the contract: features register without deleting others. Combine both intents:
import { dueFeature } from './features/due';
import { tagsFeature } from './features/tags';
const features = [dueFeature, tagsFeature];
Then git add src/main.ts and finish the merge. Re-run both features’ checks. A resolution that keeps tags and silently drops due is worse than the conflict. -X ours / -X theirs is the same reflex with extra flags — do not use it here.
If the merge is wrong, abort or revert — do not reset --hard
While the merge is in progress, git merge --abort returns you to the pre-merge state. It does not touch the worker’s branch. Git recommends a clean tree before you merge; abort cannot always reconstruct dirty files. If the merge commit already exists, git revert -m 1 <merge-sha> reverses it (-m 1 keeps the first parent — the branch you merged into).
Do not use git reset --hard. Do not git push --force. After undoing, mark that worker done, unverified again and fix the cause in its worktree. Hidden secrets or out-of-scope files on a branch are a reason not to merge: send it back or cherry-pick only the in-scope commit.
A read-only agent may explain a conflict; you still decide
If a hunk is unclear, switch to Plan (edits and bash default to ask) and paste: read the conflicted file and git show both sides; explain each intent in plain language; do not edit; do not run any command that changes state. Then you apply the rule: both sides valid and contract-compliant → combine; one side violates the contract → keep the compliant side and send the other worker back; both change the same behaviour incompatibly → stop, fix the interface task, re-dispatch. Do not let Build or --auto finish the merge unattended.
Record every conflict: file, both intents, the rule, and the checks that passed afterwards. “Resolved conflict” with no detail is not evidence.