feat: show base-relative changes in conflict panes

This commit is contained in:
2026-10-24 23:55:12 +02:00
parent c88582f2ba
commit c1bff63111
9 changed files with 509 additions and 322 deletions
+4
View File
@@ -573,6 +573,8 @@ Run **`:resolve`** in Normal mode for the current jj working copy. It opens a de
The resolver shows the editable **Resolution** on the left and a read-only **Other version** on the right, with aligned rows, line/character highlighting, context folds and synchronized scrolling. Both are projected from the current working buffer, including pre-existing unsaved edits: only conflict-marker regions are replaced by their selected alternatives. Already-merged text and edits outside those regions appear on both sides. The initial output is seeded from the first side as a normal undoable buffer change; opening never writes it to disk. References remain frozen while later edits change only the output.
Both panes show their own changes **against the selected base**, not a left-to-right removal/addition comparison: removed base lines are red with `-`, and added candidate lines are green with `+`, on either side. Replacements show the removed base text followed by the candidate text; unchanged text stays neutral. Removed base lines are display-only, with no candidate line number, caret, or editable selection. With no base (an add/add conflict), both candidates are additions against empty text. The Resolution baseline uses the same frozen working-text projection as its alternatives, preserving already-merged text and pre-existing outside edits. `resolve.base` selects the baseline through History; returning to Resolution uses that selection. Hunk navigation and `resolve.use_source` still operate on differences between the actual Draft and Alternative.
Pane borders label the editable output **Resolution** and its frozen reference **Other version**. Paths and branch-comparison metadata are omitted from these titles; unsaved state belongs only to the output, and source identity appears with the reference. Explorer **C** marks files jj still considers conflicted, including while edited/checking or confirmation is unavailable; it clears only when jj confirms resolution.
| Command | Behavior |
@@ -588,6 +590,8 @@ Pane borders label the editable output **Resolution** and its frozen reference *
**History** is separate from editing: it compares the original inputs and their base, with all sides and bases selectable for multi-sided conflicts. `config.resolve_history_layout = "columns"` (default) shows left/base/right; `"base_below"` shows left/right above a full-width base. Both layouts retain aligned changes and synchronized vertical scrolling. Tab/Shift+Tab cycles in layout order; directional pane actions follow the displayed geometry. Narrow History shows the focused source, as does base-below History when too short to display both rows of panes. Draft text, undo, caret and viewport survive view switches. Resolution uses the ordinary diff workspace, including its configured explorer, split/unified/orientation controls, source-line navigation, excerpts, focus and scrolling. Read-only Alternatives and History reject edits and saves.
Each outer History pane uses the same red-removal/green-addition presentation against the selected base. The base pane highlights original text changed by either input; addition-only rows leave a gap there. This applies to both History layouts.
Input indexes are one-based and include bases. Conflict-specific actions appear in the palette and through corresponding `config.core.resolve` methods. File navigation uses the existing picker/explorer actions: Space o opens floating search, Space e focuses the dock, Ctrl+t switches Tree/List, Ctrl+w closes it, and configured tree/selection bindings apply unchanged. Enter selects a relevant conflict file and focuses the editable Draft. Normal-mode Tab/Shift+Tab, native motions/search, context expansion and layout actions follow normal diff behavior. The complete seeded Draft can be saved even when intentional differences remain against the Alternative: those differences are not unresolved conflict markers. There is no automatic “accept both”.
**`:w` saves and checks jj**, asynchronously. Before writing, the resolver locks the working copy and validates the frozen checkout and exact on-disk file state. Checkout changes, external writes and unsafe filesystem ancestors refuse the write, including force-save. Successful writes trigger jj's normal snapshot operation, which may capture other on-disk changes. The list distinguishes unresolved, unsaved, checking, resolved and unconfirmed states. jj—not marker scanning or a manual checkbox—confirms resolution. A failed confirmation keeps saved contents and reports unconfirmed status. Resolved files remain in the session for review. Dirty drafts prevent destructive resolver/pane/tab closes.