feat(git): per-block conflict view with mine/theirs choices (#45)

Opening a conflicted file in the Changes panel now shows each conflict
block as its two sides, labelled from git's markers and tinted apart,
with Keep mine / Take theirs / Keep both per block (undoable, ^/v to
jump). Save and mark resolved writes the chosen text through the
whole-file editor's PUT /git/file (baseSha stale check) then runs
resolve done. The Merge conflicts group's buttons are text, and a
conflicted file is marked with a red ! in the Files tree.

Fix: ls-files --cached lists an unmerged path once per stage, so the
tree showed a conflicted file three times; lsFiles now dedupes.
This commit is contained in:
2026-09-25 13:35:50 +07:00
parent 52392962fb
commit 1da46f10f4
12 changed files with 709 additions and 31 deletions
+12 -3
View File
@@ -567,9 +567,18 @@ its recovery is a button too: a merge that stops on conflicts puts a banner at
the top of the Changes panel — **Complete merge** (enabled once nothing is
conflicted) and **Abort merge** (two clicks; back to where the branch was) —
and lists the conflicted files in their own **Merge conflicts** group with
**Keep mine**, **Take theirs** and **Mark resolved** (after editing the
`<<<<<<<`/`>>>>>>>` markers out in the file editor; refused while any are
left). Pull and branch switch are disabled until the merge is finished or
**Keep mine** / **Take theirs** for the whole file and **Mark resolved**.
Opening a conflicted file shows the **conflict view** instead of its diff:
each conflict block drawn as its two sides — *Mine (HEAD)* tinted green,
*Theirs (<branch>)* tinted blue, labelled from git's own markers — with
**Keep mine**, **Take theirs** or **Keep both** per block (undoable, ^/v to
jump between blocks). **Save and mark resolved** is enabled once every block
is chosen; it saves over exactly the version opened (a file changed meanwhile
is refused, `409 ESTALE`) and then marks the file resolved. **Edit by hand**
opens the plain editor, for a block neither side gets right; marking resolved
is refused while any `<<<<<<<`/`>>>>>>>` marker is left. In the Files tree a
conflicted file is listed once (git indexes it once per side) and marked with
a red **!**. Pull and branch switch are disabled until the merge is finished or
aborted.
`pull --ff-only` and the dirty-tree guard on `switch` are what keep either from
inventing a merge commit or a conflict underneath a running agent. **Create**