Arche treats conflicts differently from most version control systems. Rather than halting an operation and dropping you into a half-resolved state, Arche stores conflicts as first-class objects in the commit tree and lets the operation complete. A conflict object records three things: the common ancestor blob, the blob from one side, and the blob from the other. The conflict is materialised on disk as standard <<<<<<< / ======= / >>>>>>> markers so any editor can display and edit it without special tooling.
This design means that a merge or rebase with conflicts is a valid commit state, not a broken intermediate one. The working copy reflects reality: some files merged cleanly, some didn't, and the ones that didn't have markers you can edit at your own pace. arche status will report which paths contain conflict objects so you always know what needs attention.
arche merge <ref>
This performs a three-way merge between the working copy (the current draft), the target commit, and their common ancestor. Files where both sides made changes but the changes don't overlap are merged automatically. Files where changes overlap and can't be reconciled automatically become conflict objects in the resulting draft tree.
The resulting commit has two parents: the previous HEAD and the merged commit. Its phase is draft. It has a new change ID. Whether or not there are conflicts, the merge succeeds and HEAD is advanced to the new commit.
After a merge with conflicts, the typical resolution loop is:
arche resolve <path> for each file to replace the conflict object with the edited blob.arche snap "Resolve merge conflicts" or arche snap --amend if you want to fold the resolution into the merge commit.arche resolve internal/server/auth.go
arche resolve does not require that you have removed the conflict markers. It replaces whatever the file currently contains with a normal blob. If you resolve a file by keeping only one side's changes, that's fine too.
arche rebase <dest>
Replay replays each commit in the chain from the current lineage onto <dest>. For each step, Arche computes the diff between a commit's parent and the commit itself, then applies that diff to the current rebase tip. The replayed commit inherits the same change ID as the original, receives a new content hash (because its parent and possibly its tree changed), and an obsolescence marker is written linking the old hash to the new one.
When a diff can't be applied cleanly at a step, the conflict is stored as a conflict object in that replayed commit and the rebase continues to the next commit. All remaining commits are replayed regardless. At the end, the working copy is materialised from the tip of the rebased chain, which may contain conflict markers in several files. arche status lists every path with a conflict object so you know what needs attention. Resolve each file, run arche resolve <path>, then arche snap.
Rebasing public commits requires --force-rewrite:
arche rebase main --force-rewrite
This is intentional friction. Rewriting public history is a coordination event and the flag communicates that you've made a deliberate decision.
There are three typical ways to resolve a conflict after editing the file:
The most common path is editing the conflict markers directly in your editor. After deleting the markers and keeping the version you want, save the file and run:
arche resolve <path>
If you want to discard your changes and take the incoming version entirely, copy the ======= to >>>>>>> section into the file body, delete the markers, and resolve. If you want to keep your version entirely, do the same with the <<<<<<< to ======= section.
After resolving all conflicts, check arche status to confirm no conflict objects remain, then snapshot or amend.
When you amend a commit that has other draft commits stacked on top of it (via arche snap --amend), Arche automatically rebases all the downstream drafts. This is the mechanism behind the stack workflow.
The auto-rebase walks the descendants of the amended commit in topological order and replays each one onto the new tip. If any downstream commit conflicts with the amendment, the conflict is stored as an object in that commit, the auto-rebase continues, and you are left with a working copy that may have conflict markers in one or more of the downstream commits. The operation log records the full scope of what happened, so arche undo will unwind all of it atomically.
This is a deliberate design choice. The alternative, pausing the auto-rebase and requiring interactive conflict resolution before continuing, would make amending a mid-stack change much more disruptive. Stored conflicts let you finish the push first and resolve at your own pace.
When two people edit the same issue's body text concurrently in separate clones, a sync will detect the conflict at the CRDT level. Arche stores a body_conflict event in issues.db. arche status reports this so it doesn't go unnoticed, and the conflict is resolved through the forge web interface, which presents both versions and lets you choose or merge them. Issue comment threads and label changes don't conflict in this way because they're append-only or use last-writer-wins semantics respectively.