jesseduffield / jesseduffield/lazygit
Improved diff UX
- Dominant language
- Go
- Stars
- 82.4k
- Forks
- 3k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 19
Description
**Is your feature request related to a problem? Please describe.**
I want to revamp the UX for diffing refs.
Currently the way it works is that you select a ref (e.g. a commit, branch, or tag), open up a menu, choose to diff it (so that it becomes the `from` in `git diff from..to`, and then if you select another ref the main view will show the diff. If you hit enter on that other ref it'll show you the commits of that ref (sub-commits view) and if you hit enter again (on the top commit) you'll see the files of the diff (diff-files view).
This has a couple of shortcomings:
* having to go through the top commit to see the diff files is not intuitive
* we show A..B (and you can see B..A by reversing it through a menu) but often people want to see A...B and B...A. This is especially true when comparing a branch to its upstream because that gets you the commits to push and the commits to pull.
* sometimes people forget they're in 'diff' mode and it causes confusion
BTW here's the difference between A..B and A...B from this [stackoverflow post](https://stackoverflow.com/questions/7251477/what-are-the-differences-between-double-dot-and-triple-dot-in-git-dif)

There's two separate problems that need solving:
* selecting the two refs to diff
* showing the diff
## Selecting the two refs to diff
When we press the diff keybinding on a ref I want these options (we can sort out the wording/ordering later):
* diff against upstream (if we're on a branch with an upstream)
* select for diff
* diff against selected ref 'feature/my-branch' (if a ref has been selected)
* enter ref to diff (brings up a prompt with suggestions)
* (other options we can add later)
If you choose `select for diff` it highlights the ref and lets you use it later via the `diff against selected ref` menu item, but importantly that's ALL it does. Currently we show the diff in the main view as you move your cursor through different refs but with this new approach we'll instead only show diff stuff once you've explicitly selected both refs (at which point you'll be inside a diff-specific view and upon escaping out you're back to normal). So if you forget that you had selected a ref ages ago, but you're not currently inspecting e.g. diff files, it doesn't matter because it doesn't impact the UI.
## Showing the diff
Once I've got the two refs that I'm diffing I want to see the following options:
- A...B (e.g. '5 ahead')
- B...A (e.g. '3 behind')
- A..B (e.g. 'compare mybranch to origin/mybranch'
- B..A (e.g. 'compare origin/mybranch to mybranch'
If you pick one of the first two options, you may want to see the commits or the changed files. If you pick one of the second two, it makes less sense to see the commits because it's a direct comparison from one commit to the other. So if you pick one of the second two we can take you to the diff-files view, and if you pick one of the first two we need to give you the option to then choose between seeing files or commits.
As a first cut we can just handle these options through menus...
### Menu items in side views
...But after the first cut, I wouldn't mind experimenting with a UI that allows us to add menu items to the top of a side view. So rather than have a menu for choosing between seeing commits and seeing files, we could instead show the commits as if it were the sub-commits view but have the first item be a menu item for viewing the files.
Likewise, rather than have a menu for choosing whether you want A...B, B...A etc, we could stay in a side view and have those options sitting on top of the commits of A and B (ending at their merge-base). This has a few benefits:
* your eyes don't need to jump from the side view to a popup in the middle of the screen
* if say the A..B option is selected, we can show the diff in the main view without it being blocked by a popup menu
* we can visually indicate in the commits section of the view those commits which we would be comparing given the currently selected menu item. This will give users a better understanding of what they're actually doing.
* menus are transient, so if I want to view the ahead changes and then the behind changes I'll need to press the diff keybindng, select the ref to compare to, select 'ahead', select 'files', then escape, then press the diff keybinding again, select the ref again, select 'behind', select commits. If we instead used a dedicated side-view we could select the ref to compare to, select 'ahead', select 'files', hit escape, select 'behind', select 'files'. So much easier to get around.
There's various things to consider here:
* keybindings relevant to commits won't be relevant to menu items so we'll need to distinguish between keybindings that are specific to the view (e.g. navigation) and keybindings that are relevant to a given item
* would we have keybindings for jumping-to and selecting one of the menu items, as we do in regular menus? Could that conflict with keybindings we want to add to commits?
With this pattern we could also add shortcuts like showing the 'changes to push' and 'changes to pull' menu items at the top of a branch's commits view.
## Questions
* Does this proposal _without_ the menu-items-in-sideviews part sound like an improvement upon the existing UX?
* What do we think about the idea of menu items in sideviews?
* What do people think generally about the above? Is something important being ignored? Could this be smoother?
Contributor guide
Assessment
This issue has not been assessed yet.