Conflicts
How Bowline preserves both sides when work diverges, keeps your live files stable, and never writes conflict markers into your source.
A conflict is a divergence Bowline can't merge while preserving both sides' intent. Conflicts are normal and safe in Bowline: instead of picking a winner or writing markers into your files, the sync engine keeps your file a coherent version and preserves the other side as a conflict-aside file next to it. This page explains the model; the resolve a sync conflict guide walks through the steps.
When a conflict starts
Most divergent work never conflicts: edits to different files from different devices sync past each other and advance the Workspace Head automatically. A conflict starts when two devices diverge on the same file — each changed it since the last state they agreed on, and the engine can't keep both versions at one path.
Conflict-aside files
When that happens, the sync engine writes a deterministically named aside file next to the affected file:
~/Code/acme/web/src/auth/callback.ts
~/Code/acme/web/src/auth/callback.ts.bowline-conflict.3f2a1c9dThe name shape is <path>.bowline-conflict.<prefix>, where the prefix is
derived from the incoming content so repeated conflicts on the same path never
collide. Three properties of that shape are deliberate:
- The marker is appended after the original name, so the aside no longer ends
in
.ts. Source globs, tsconfigincludepatterns, linters, and language servers skip it instead of compiling a second copy of your module. - It contains no spaces, quotes, or parentheses, so the path survives a shell
word, a
git add, and an agent prompt without quoting rituals. - It is derived only from the path and the incoming content — no device name, no timestamp — so two devices that receive the same conflict produce the same aside name and converge on one file instead of multiplying copies.
Both versions are ordinary files:
- The file at the real path stays a coherent version. Your editor, build, and tools keep working; Bowline never splices conflict markers into your source.
- The aside holds the other side's version, byte for byte. Nothing is lost.
- The aside syncs to your other devices like any other file, so every trusted device sees the same conflict and any of them can reconcile it.
Git's own state is the exception
Bowline never writes an aside inside a .git/ directory. A second index or
HEAD file would corrupt the repository rather than preserve anything, so a
divergence in git's internal state keeps your local copy and republishes it.
Working-tree files, including uncommitted work, conflict normally.
Conflicts stay passive but visible
A conflict never steals your focus or auto-launches a repair. Conflict-asides surface as attention across every surface and stay there until you reconcile them. You decide when.
| Surface | What it shows |
|---|---|
bowline conflicts | Every aside, with the command to resolve. |
bowline status --root ~/Code --project <path> | Conflict-asides and the affected paths. |
bowline tui | The same attention state, interactively. |
| Menu Bar Status App (macOS) | Ambient attention count. |
Reconciling
bowline resolve <aside-path> takes one of three verbs, and exactly one is
required — Bowline will not guess which side of your own work to keep.
| Verb | Effect |
|---|---|
--diff | Print the difference between the two. Changes nothing. |
--keep-local | Keep the file as it is; discard the incoming version. |
--take-remote | Replace the file with the incoming version. |
All three are ordinary file operations underneath, and the aside's absence is what clears the conflict everywhere. So the manual path works identically: open both files, fold in what you want, delete the aside. Any tool that can edit files can reconcile a conflict — your editor, a diff tool, or a coding agent pointed at the two paths.
Next steps
- Resolve a sync conflict: the step-by-step reconciliation flow.
- Workspace model: snapshots and heads.
- Status and health: how conflicts surface in status.