Skip to content

merge_tools: add new TUI for resolving conflicts#9078

Draft
scott2000 wants to merge 5 commits intomainfrom
scott2000/resolve-tui
Draft

merge_tools: add new TUI for resolving conflicts#9078
scott2000 wants to merge 5 commits intomainfrom
scott2000/resolve-tui

Conversation

@scott2000
Copy link
Contributor

@scott2000 scott2000 commented Mar 11, 2026

IMO current builtin diff editor doesn't work great with jj resolve. It only supports 2-sided conflicts, it doesn't render conflict labels, and the way that conflicts are rendered is confusing except in the most basic cases. After seeing jj arrange, I thought I'd take a shot at making a custom TUI for jj resolve that tries to solve these issues. This is just a work in progress still, but I thought I'd put it up as a draft in case anyone wants to try it out and give feedback.

Features:

  • Supports partial resolution of conflicts
  • Supports conflicts with more than 2 sides
  • Supports non-file conflicts (e.g. directory-file)
  • Displays conflict labels for each side
  • Can scroll through file using mouse

Views and key bindings

File list

This view is only visible when there are multiple files with conflicts.

  • down/up (j/k) - navigate
  • enter/space - select file
  • backspace/delete - delete resolution for file
  • q - discard changes
  • c - confirm changes
file list

Conflict viewer

This view is used for resolving normal conflicts. There is a separate view with fewer features for resolving conflicts involving deleted files, directories, symlinks, and git submodules.

  • down/up (j/k) - select conflict
  • left/right (h/l) - select term within conflict
  • enter/space - resolve conflict by only keeping the currently selected term
  • backspace/delete - resolve conflict by deleting it
  • a - resolve conflict by keeping all sides
  • r - use same resolution as current conflict for all remaining conflicts
  • d - toggle diffs
  • b - toggle showing bases vs sides
  • e - open file in editor to manually resolve conflicts
  • q - discard changes
  • c - confirm changes
conflict viewer

To-do

  • Binary file detection
  • CRLF support
  • Missing terminating newline support
  • Display key bindings in UI
  • Allow customizing colors in config
  • Update documentation
  • Add test cases

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, demos/)
  • I have updated the config schema (cli/src/config-schema.json)
  • I have added/updated tests to cover my changes
  • I fully understand the code that I am submitting (what it does,
    how it works, how it's organized), including any code drafted by an LLM.
  • For any prose generated by an LLM, I have proof-read and copy-edited with
    an eye towards deleting anything that is irrelevant, clarifying anything
    that is confusing, and adding details that are relevant. This includes,
    for example, commit descriptions, PR descriptions, and code comments.

@scott2000 scott2000 force-pushed the scott2000/resolve-tui branch 4 times, most recently from 32d89b6 to 78bbf56 Compare March 11, 2026 02:24
Previously, we only looked ahead a single term when determining whether
to write the current added term as a snapshot or not, meaning it didn't
always find the optimal solution. This commit changes the implementation
to always find the snapshot index which minimizes the diffs. Both
implementations require `O(n)` diffs, but it could be slightly more
expensive. Since most conflicts only have two terms, this isn't likely
to be an issue though.
This removes the special case for using "base" instead of "base #1" when
there's only one base, but since all new conflicts will have labels,
this should be fine.
Currently, ratatui doesn't provide much support for scrollable areas
except for lists and single paragraphs. This widget allows rendering an
arbitrary series of widgets inside a scrollable block.
@scott2000 scott2000 force-pushed the scott2000/resolve-tui branch from 78bbf56 to db725fa Compare March 11, 2026 04:00
@PhilipMetzger
Copy link
Contributor

In general this poses the question why this isn't going into scm-record, if its our blessed implementation. It makes even less sense if we want to take over stewardship of it in a few years when the legal situation around the project has improved.

@PhilipMetzger
Copy link
Contributor

I'm also very interested in @arxanas opinion on this.

@thoughtpolice
Copy link
Member

thoughtpolice commented Mar 11, 2026

I actually do love the "pages" so you can see the sides of the conflict in place around the file. That's smart

Have you thought about what it would take to do a 3-pane terminal view? Ilya has a bit of prior art with diffedit3. I'd really love something nice here, a good TUI would be wonderful.

@scott2000
Copy link
Contributor Author

In general this poses the question why this isn't going into scm-record, if its our blessed implementation.

I think it might make sense to have them be separate. If I understand correctly, scm-record is mainly for modifying diffs and commits, not for resolving conflicts.

Have you thought about what it would take to do a 3-pane terminal view?

The main difficulty with this is that I wanted to make something that can support many-sided conflicts, but the normal 3-pane view usually only for 2-sided conflicts. I do think this would be really nice to have though. Let me think about it and try to come up with a good UI for it.

Maybe it could work where the left panel is a base snapshot to edit, and the middle and right panels are used to show a side-by-side diff to apply to that snapshot (with many-sided conflicts being achieved by having a way to select which diff is currently being applied)? I suppose this is similar to the idea of doing repeated invocations of a 3-pane viewer (#6702), but ideally it would be nice to let the user freely navigate between the sides instead of enforcing an order.

@PhilipMetzger
Copy link
Contributor

In general this poses the question why this isn't going into scm-record, if its our blessed implementation.

I think it might make sense to have them be separate. If I understand correctly, scm-record is mainly for modifying diffs and commits, not for resolving conflicts.

Sorry this really doesn't answer the question I asked. I mean scm-record is something intended to be shared infrastructure for multiple VCS's and while it currently only understands diffs and commits having support for multi-sided conflict resolution is something surely @arxanas wanted to implement there. I also think having such an infrastructure will be needed for multiple splits later, so not doing costs more for both projects.

To me this comes across "I don't understand the required changes I need to make to scm-record, so I just rolled my own" which is imho bad engineering.

@scott2000
Copy link
Contributor Author

having support for multi-sided conflict resolution is something surely @arxanas wanted to implement there.

I wasn't aware of this. To me, conflict resolution seems to require a different interface than the existing interface for scm-record, so I think it makes sense that they would be implemented as separate tools. If I did add this functionality to scm-record, I don't think I would be able to take advantage of much of the existing implementation; it would just end up being a separate UI that happens to be in the same repo.

I also think having such an infrastructure will be needed for multiple splits later, so not doing costs more for both projects.

I don't see how this is relevant. I don't think adding a new conflict resolution interface to scm-record would help with adding support for multiple splits at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants