Merges
A merge applies the work an agent did on a branch back to main. AVC’s merge is a three-way merge: it compares the base snapshot (where the branch was created), the current state of main, and the branch’s HEAD snapshot to decide what to apply.
If diffing answers “what did the agent do?” and branching answers “where did it work?”, merging answers “what reaches the main project?”.
How the three-way merge works
Section titled “How the three-way merge works” base snapshot / \ (main edits) (branch edits) / \ main HEAD branch HEAD \ / \ / merged mainFor every file:
Modified on main? | Modified on branch? | Outcome |
|---|---|---|
| ❌ | ✅ | Clean apply — branch version overwrites main |
| ✅ | ❌ | Skipped — main’s version stays |
| ❌ | ❌ | Untouched — no change |
| ✅ | ✅ | Conflict — both versions diverged since base |
Clean and skipped files apply automatically. Conflicts are surfaced to you.
Conflict markers
Section titled “Conflict markers”When AVC detects a conflict, it writes the file with standard conflict markers to your working tree:
<<<<<<< mainthe version from main=======the version from the branch>>>>>>> feat-authYou resolve the conflict by editing the file (just like Git), then take a new snapshot to mark the resolution.
Always reversible
Section titled “Always reversible”Before every merge, AVC takes an automatic snapshot of main labelled Pre-merge safety snapshot. If the merge goes wrong — wrong files applied, conflicts you don’t want to deal with, anything — undo it with:
avc merge --abortThis restores main from the pre-merge snapshot. The agent branch is untouched.
Commands
Section titled “Commands”avc merge <branch> # apply clean changes, surface conflictsavc merge <branch> --preview # dry-run: show counts only, modify nothingavc merge --abort # restore main from the pre-merge snapshotPreview output:
Preview: merge "feat-auth" → main Clean: 12 file(s) Conflicts: 1 file(s) Skipped: 0 file(s)This lets you decide whether to proceed before any files are touched.
What the merge records
Section titled “What the merge records”Every merge attempt is logged in the merges and merge_files tables:
| Table | Stores |
|---|---|
merges | merge ID, branch, timestamp, base snapshot, target branch HEAD, pre-merge safety snapshot ID |
merge_files | per-file decision: clean / conflict / skip |
You can query these via the database if you want a merge audit trail.
Implementation notes
Section titled “Implementation notes”The merge engine opens the database in three separate phases to avoid lock contention:
- Plan — read all three snapshots’ file lists, compute per-file decisions
- Apply — write clean files to the working tree, write conflict markers where needed
- Record — write the
mergesrow and per-file results
Each phase opens and closes the DB connection. This is one of the architectural rules in CLAUDE.md — one DB connection per operation.
When merge is appropriate
Section titled “When merge is appropriate”Merge a branch when:
- The agent’s work has been reviewed (by you or by tests)
- You want to incorporate the changes into
mainfor downstream work - The branch is “done” and you no longer need its isolation
If the agent’s work was bad, don’t merge — delete:
avc branch delete feat-bad-ideaNothing reaches main. The workspace is cleaned up. You’re back to square one.
What merge is not
Section titled “What merge is not”- Not a Git merge — no merge commits, no
--no-ff, no octopus merges - Not a rebase — branch snapshots are preserved as-is, they’re just applied to
main’s working tree - Not automatic — you always run it explicitly; agents don’t merge their own work