Resolve conflicts¶
In TOVIO a conflict is stored data, not a blocking error. When two changes can't be merged automatically, the merge completes and the conflict is saved as an object you resolve when you're ready. Your repository stays fully operational with open conflicts: you can keep editing, committing, switching, and stacking on top. Think of a conflict like a type error you can see and work around — not a crash that halts everything.
A stored conflict is success, not failure
A land that stores conflicts exits 0 and reads as "nothing is blocked." It will never show up
as a fatal:-style error. The only hard limit: a change with unresolved conflicts can't
land onto a protected lane — because shared code must stay buildable.
Most of this surface is implemented
tovio resolve (with all its flags), tovio conflicts (the list), the stored-conflict object, and
the protected-lane land gate are implemented in the current source tree — the sound-merge engine,
with rerere replay, is wired into land, rebase, switch, and resolve. Conflicts are addressed
by path, not by a conflict id. Three things on this page are still ahead: a standalone
tovio merge verb (integration is tovio land), the tovio conflicts show / reopen
subcommands, and the tovio cx short alias. Where those appear below, read them as the designed
surface. No generally available package has been published.
flowchart LR
M["tovio land"] --> S["Stored conflicts<br/>(one per path)"] --> R["tovio resolve<br/>(kind-directed)"] --> D([✓ resolved]) --> L["tovio land"]
More diagrams for every kind, the land gate, and rerere replay: Conflict workflows.
What a stored conflict looks like¶
A land that can't auto-merge a path completes and tells you plainly:
✓ landed `feature/cgm-sync` into `main` with 3 conflict(s) blake3:fd9764d8b6…
⚠ content src/integrations/cgm/dexcom.ts
⚠ content src/integrations/cgm/types.ts
⚠ content tests/integrations/cgm.test.ts
nothing is blocked — the conflicts are stored as data.
resolve them: tovio resolve
list them: tovio status --conflicts
Open conflicts also surface in tovio status, so you never lose track of them.
List open conflicts¶
1 open conflict(s):
src/integrations/cgm/dexcom.ts (content · unresolved)
→ Next: `tovio resolve <path>` to resolve a conflict (or `--ours` / `--theirs`)
Each row is the conflicted path, its kind, and its status. The command exits 0 — it reads as
attention, never as an error. To see why a path conflicted — the merge base, both sides, and which
decision each file got — use the merge lens of tovio explain
(tovio explain merge <lane> --into main), or tovio explain rerere <path> for whether a recorded
resolution would replay.
Designed inspection subcommands
The CLI specification also designs tovio conflicts show for one conflict's kind, both sides, and
base; it is not implemented yet, and neither is the tovio cx short alias.
Resolve a conflict¶
With no strategy flag, resolve walks each open conflict — or one, if you name its path — in a
console-native hand-merge: a unified ours-vs-theirs diff per region, and a per-region choice (keep a
side, take both, hand-merge inline). No conflict markers ever touch your files and no external editor
opens:
$ tovio resolve # walk every open conflict
$ tovio resolve src/integrations/cgm/dexcom.ts # just this one
For a quick, non-interactive decision on a content conflict, pick a side:
$ tovio resolve src/integrations/cgm/dexcom.ts --ours
$ tovio resolve src/integrations/cgm/dexcom.ts --theirs
$ tovio resolve src/integrations/cgm/dexcom.ts --base
✓ Resolved — kept ours of `src/integrations/cgm/dexcom.ts` blake3:a7659add14…
All conflicts resolved · undo with `tovio undo`
If you merged the file by hand (or in a merge editor), record the bytes on disk as the resolution
with --working-tree. --ai asks the configured resolver plugin to propose a resolution — with no
resolver bound, it declines. At most one strategy flag per call.
Conflicts come in kinds¶
resolve does the right thing for each kind — a text merge isn't always the answer:
| Kind | What it means | How you resolve it |
|---|---|---|
| content | Both sides edited overlapping lines | Region-by-region merge, --ours / --theirs / --base, or --working-tree |
| add/add | Both sides added the same path with different content | Same choices as a content conflict |
| delete/modify | One side deleted a file the other edited | A keep-or-delete choice: --keep or --delete — not a text merge |
| rename/edit | One side renamed, the other edited | Usually auto-merged; only surfaces if edits overlap |
| rename/rename | Both sides renamed to different paths | Pick the path: --rename-to <path> |
| semantic | A change broke references another change relied on | Advisory — a warning listing the affected changes; doesn't block unless a protected lane requires the semantic check |
$ tovio resolve src/integrations/cgm/legacy.ts --keep
$ tovio resolve src/integrations/cgm/dexcom-client.ts --rename-to src/integrations/cgm/client.ts
Record why¶
A resolution is a decision worth remembering. --why "<one or two sentences>" attaches an attested
rationale to the resolving commit (optionally with --decision, --rejected "<option> :: <reason>",
--dead-end, --confidence low|medium|high, --ref), and tovio log --why shows it later. For a
policy-protected path the rationale is sealed automatically.
These flags — and --region — ride a one-shot resolution, so they require a path and a strategy flag.
Authoring a rationale from inside the interactive walk is still ahead; tovio resolve --why "…" on its
own is a usage error naming the strategy flags it needs.
A resolution propagates — resolve once¶
When you resolve a conflict, the resolution is recorded and replayed wherever the same conflict
appears again — you don't re-resolve the identical conflict in three different changes. Resolve once;
TOVIO carries it across. Region choices made with --region replay on a later land alongside the
whole-file resolution.
It also persists across history rewriting. A resolution recorded before you
amend, rebase, split, or absorb still applies afterward — rewriting your history doesn't make a resolved
conflict come back, and it won't reappear on your next sync. tovio explain rerere shows, per open
conflict, whether a recorded resolution matches and would replay — and if not, exactly why.
Resolution reuse is implemented
Both halves of the behavior above are implemented in source: resolution reuse for the identical
conflict, and the rerere replay that carries a resolution across every context and through a later
land and history rewriting. It is part of the sound-merge engine wired into resolve and land,
but is not a claim that a generally available binary has been published.
Reopen a resolved conflict¶
Changed your mind, or resolved one wrong? The resolution is op-logged, so
tovio undo reverses it and the conflict is open again.
Designed reopen subcommand
The CLI specification also designs tovio conflicts reopen for reopening a specific resolved
conflict without unwinding the op-log; it is not implemented yet.
The one hard limit: protected lanes¶
A conflict never blocks your in-flight work, but it does block landing onto a protected lane
(main, release). Those lanes are guaranteed buildable, and a file holding both sides of a
conflict won't compile. So tovio land onto a protected lane refuses with
TVO-CONFLICT-003 until the change is conflict-free:
✗ Cannot land: 1 unresolved conflict(s)
Landing `my-lane` into protected `main` leaves 1 unresolved conflict(s):
content src/integrations/cgm/dexcom.ts
…
Check landability any time with tovio change health <change-id> — it reports whether a change is
conflict-free, how stale it is, and whether it is ready to land, without changing anything.
Pulling a teammate's conflicted change is gated too
Within your own stack, conflicts are non-blocking. But TOVIO won't silently materialize a
teammate's unresolved conflict into your working tree and break your build. That cross-developer
boundary — and the --isolate option to build against the last-known-clean version — lives in the
collaboration guides.
Where to go next¶
- Ready to ship the now-clean change? → Land a change
- Want the full picture of open conflicts across your stack? → Read your status
- Resolved one wrong? → Undo and redo recorded operations
Last reviewed September 9, 2026
Suggest an improvement to this page Not for security reports — see disclosure