This commit implements the ability to cycle backward through different
all branches log visualization modes, complementing the existing forward
cycling functionality. Users can now press 'A' (Shift+a) to cycle in
reverse through the available log graph views, improving navigation
efficiency when they overshoot their desired view.
Changes:
- Added RotateAllBranchesLogIdxBackward() method to BranchCommands for
backward rotation through log command candidates
- Introduced AllBranchesLogGraphReverse keybinding configuration with
default key 'A' (uppercase)
- Implemented switchToOrRotateAllBranchesLogsBackward() handler in
StatusController that mirrors forward cycling logic
- Added English translation for "Show/cycle all branch logs (reverse)"
The implementation uses modulo arithmetic with proper handling of
negative indices to ensure seamless backward cycling through the
available log visualization options.
The worktrees tab now displays the checked-out branch (or detached HEAD
state) for each worktree, making it much easier to see which worktree
holds which branch.
This is useful when you need to "unlock" a branch that's occupied by
another worktree: you can now clearly see which worktrees are on a
branch vs detached, without having to select each one individually.
Also rename the "(main)" label to "(main worktree)" to avoid confusion
with the common "main" branch name, and move it after the branch column.
I always press 'd' in the patch building view, expecting that I can do
exactly what I can do in the staging view, to find out I need to go
space -> ctrl+p -> d and I think it's time to honour the muscle memory
and support this convenience keybinding.
Only mention resetting the patch when there actually is one. This way users have
to read less text in the normal case, and the added note hopefully stands out
more if there is one. Also, separate the note from the previous text by a blank
line.
"Remove" can be confusing when a deleted file is selected; in this cases it
actually "un-removes" it. "Discard" hopefully makes it clearer that we are
talking about the change to a file, and not the file itself.
I've optimised for muscle memory backwards compatibility here:
- Outside interactive rebase: press 'f' then instead of a confirmation
panel, a menu appears where you can choose to keep the selected commit's
message
- Inside interactive rebase: press 'f' then press 'c' to see the menu
for keeping the message, where if you press 'c' again it will retain the
current message. so 'fcc' is the chord to press.
We're also now showing the -C flag (which is what enables the behaviour)
against the todo.
I've picked the 'c' keybinding because 'C' was taken and it corresponds
to the flag. Previously that showed a warning about a change in
keybinding for cherry picking but it's been ages since we've made that
change so I'm happy to retire it.
It's been ages since we changed the key, users should hopefully be used to it by
now, and we want to reuse the key for something else later in the branch.
Co-authored-by: Stefan Haller <stefan@haller-berlin.de>
The confirmation used to make sense back when the Open MergeTool command was its
own top-level command; however, that command was changed in 703f053a7e to open a
menu instead, and Open MergeTool is now just a submenu entry in that menu, so it
no longer needs a confirmation.
Most of our prompts don't (shouldn't) allow empty input, but most callers didn't
check, and would run into cryptic errors when the user pressed enter at an empty
prompt (e.g. when creating a new branch). Now we simply don't allow hitting
enter in this case, and show an error toast instead.
This behavior is opt-out, because there are a few cases where empty input is
supported (e.g. creating a stash).
This will put whatever git's default merge variant is as the first menu item,
and add a second item which is the opposite (no-ff if the default is ff, and
vice versa).
If users prefer to always have the same option first no matter whether it's
applicable, they can make ff always appear first by setting git's "merge.ff"
config to "true" or "only", or by setting lazygit's "git.merging.args" config to
"--ff" or "--ff-only"; if they want no-ff to appear first, they can do that by
setting git's "merge.ff" config to "false", or by setting lazygit's
"git.merging.args" config to "--no-ff". Which of these they choose depends on
whether they want the config to also apply to other git clients including the
cli, or only to lazygit.
Replace merge-tool with merge options menu that allows resolving all
conflicts for selected files as ours, theirs, or union, while still
providing access to the merge tool.
So far, confirmations and prompts were handled by the same view, context, and
controller, with a bunch of conditional code based on whether the view is
editable. This was more or less ok so far, since it does save a little bit of
code duplication; however, now we need separate views, because we don't have
dynamic keybindings, but we want to map "confirm" to different keys in
confirmations (the "universal.confirm" user config) and prompts (hard-coded to
enter, because it doesn't make sense to customize it there).
It also allows us to get rid of the conditional code, which is a nice benefit;
and the code duplication is actually not *that* bad.
When the useHunkModeInStagingView config is on and you enter the staging view
with hunk selection enabled, it is confusing to see "a: Select hunk" in the
options view at the bottom.
This way we don't have to update the text and all translations every time we
bump the version.
Remove the year from the error text, it's cumbersome to update and I don't find
it very important to have in the message.
Also remove the invitation to file an issue; I don't find it very likely that we
are going to relax the minimum git requirement again.
The version choice is a little arbitrary, but see discussion at
https://github.com/jesseduffield/lazygit/pull/4559#issuecomment-2876201680.
The main reason why I'm updating the version now is that versions before 2.27
had a bug with branch sorting, where sorting by -committerdate (which will be
our default soon) would sort branches that point at the same commit in reverse
alphabetical order rather than alphabetical order. While this is only slightly
annoying but not a huge deal for users, it makes maintaining our integration
tests across versions very hard. So I wanted to update to at least 2.27 to get
around this problem, and went with 2.32 after the discussion linked to above.
The choice of which versions to run integration tests on is pretty arbitrary
too, I just picked some at random which are about 5 to 6 minor versions apart.
These were found by commenting out the initialization of the struct literal in
EnglishTranslationSet.TranslationSet(), and then running
$ punused pkg/i18n/**/*.go
Punused can be installed with `go install github.com/bep/punused@latest`.
For the case of creating a new branch by moving commits to it, we were using the
current (old) branch name in the stash name; change this to use the new name
instead.
Unlike moving a patch to the index, applying or reverting a patch didn't
auto-stash, which means that applying a patch when there's a modified (but
unstaged) file in the working tree would error out with the message "error:
file1: does not match index", regardless of whether those modifications conflict
with the patch or not.
To fix this, we *could* add auto-stashing like we do for the "move patch to
index" command. However, in this case we rather simply stage the affected files
(after asking for confirmation). This has a few advantages:
- it only changes the staging state of those files that are contained in the
patch (whereas auto-stashing always changes all files to unstaged)
- it doesn't unnecessarily show a confirmation if none of the modified files are
affected by the patch
- if the patch conflicts with the modified files, the conflicts were "backwards"
("ours" was the patch, "theirs" the modified file); it is more logical if "ours"
is the current state of the file, and "theirs" is the patch.
It's a little unfortunate that the behavior isn't exactly the same as for "move
patch to index", but for that one we do need the auto-stash because of the
rebase that runs behind the scenes.
Previously we would call pullFiles() from the pick() handler if we were not in a
rebase, assuming that the default keybinding for both is "p". This needn't be
the case of course, if the user has remapped one or the other.
The consequence of this was that swapping the keybindings for "pullFiles" and
"pushFiles" would work in all panels except the Commits panel (unless "pick" was
also remapped in the same way).
Fix this by using the new AllowFurtherDispatching mechanism of DisabledReasons
to pass the keybinding on to the next handler.
The default binding for ConfirmInEditor is <a-enter>, which has two problems:
- some terminal emulators don't support it, including the default terminal on
Mac (Terminal.app)
- on Windows it is bound to toggling full-screen
Ideally we would use <c-enter> instead (and Command-Enter on Mac), but neither
is possible without https://github.com/gdamore/tcell/issues/671, so for the time
being add an alternate keybinding which works everywhere.
Show both bindings in the footer of the commit description panel if they are
both non-null. While we're at it, fix the footer for the case where either or
both of the keybindings are set to <disabled>.
And finally, change "commit" to "submit" in that footer; we use the same panel
also for creating tags, in which case "commit" is not quite right.
This is very similar to what we are doing for staging or discarding hunks in the
Files panel. Git doesn't allow applying patches with a zero context size (unless
you use the --unidiff-zero option, which is discouraged).
In this commit this is only possible by pressing '0' in a side panel; we'll add
mouse clicking later in the branch.
Also, you can't really do anything in the focused view except press escape to
leave it again. We'll add some more functionality in a following commit.
We treat the .git/sequencer/todo file as read-only. Technically it seems it
would be possible to treat it as modifiable in the same way as
.git/rebase-merge/git-rebase-todo, effectively turning a cherry-pick or revert
that stops at a conflict into an interactive rebase; however, git itself doesn't
allow this (there is no "git cherry-pick --edit-todo"), so it seems safer not to
rely on it.
Theoretically it would be possible to allow modifying the rebase todos when a
cherry-pick or revert conflicts in the middle of a rebase. However, it would
introduce a bit of complexity to support this, as we would have to be able to
distinguish between rebasing todos and cherry-picking/reverting todos, which we
currently can't; it could also be a bit error-prone as far as edge cases are
concerned. And it's really a pretty uncommon situation, so it doesn't seem worth
it, and we just forbid all modifications to todos whenever we are cherry-picking
or reverting.
It is useful to see if the conflicted commit was a "pick" or an "edit". What's
more, we're about to add support for showing cherry-picks and reverts, and
seeing that a conflicted commit was a revert is important because its diff is
backwards compared to the diff of the conflicting files in the Files panel.
When you are in the middle of a rebase, and you cherry-pick a commit which
conflicts, it helps to be clear on whether you are prompted to continue the
cherry-pick or the rebase.
It is shown either when committing with `w`, or when typing the skipHooks prefix
if there is one. This should hopefully make it clearer when the hooks are run
and when they are not.
For the less common conflict types DD, AU, UA, DU, and UD, we would previously
only show "* Unmerged path" in the main view, which isn't helpful. Also, for
some of these we would split the main view and show this text both in the
unstaged changes and staged changes views, which is a bit embarrassing.
Improve this by offering more explanation about what's going on, and what the
most likely way to resolve the situation is for each case.
This is useful for copying the entire content of the selected file as it was at
the selected commit.
We only add it to the commit files panel; it is not needed in the files panel,
because there you can simply press "e" to edit the file.
Rewording a commit at the beginning of a long branch can take very long;
without this change, the commit message panel would stay visible with a blinking
cursor during that time, which is very confusing.
This has the slight downside that it will say "Rebasing" in the lower right
corner until the operation is done; but we already have this problem when doing
custom patch operations, or dropping changes from a commit, so it's not new, and
we can think about how to fix all these another time.