1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-07 03:22:01 +03:00

6499 Commits

Author SHA1 Message Date
github-actions[bot]
04bc1879af README.md: Update Sponsors 2025-06-05 11:24:50 +00:00
Stefan Haller
aa331e52b8
Fix assigning custom key to pullFiles command in the Commits panel (#4617)
- **PR Description**

Improve the dispatching of key bindings so that remapping "pullFiles" to
a different key works correctly in the Commits panel.

Fixes #4614.
2025-06-05 13:24:34 +02:00
Stefan Haller
c752f3529b Remove the pick vs. pull hack
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.
2025-06-05 13:20:39 +02:00
Stefan Haller
3e26be9845 Optionally pass disabled commands on to next handler
If a DisabledReason has its AllowFurtherDispatching flag set, it is returned as
a ErrKeybindingNotHandled error, instead of shown as a toast right away. This
allows gocui to continue to dispatch the keybinding, and we can unwrap the error
at the other end (in our global ErrorHandler) and display it then.

This allows having keybindings for the same key at the local and global levels,
and they will continue to be dispatched even if the first one returns a
DisabledReason. It is opt-in, so we only use it for cases where we know that a
local and a global handler share the same (default) keybinding.
2025-06-05 13:20:38 +02:00
Stefan Haller
37b118f4fb Cleanup: restructure code for clarity
There was no reason to declare a variable for disabledReason, assign it inside
the "if binding.GetDisabledReason != nil" statement, and then check its value
again after that if statement. Move all that code inside the first if statement
to make the control flow easier to understand.
2025-06-05 13:20:38 +02:00
Stefan Haller
9e64f7dd66 Bump gocui and adapt lazygit code
Adaptions are for this gocui commit:

Cleanup: remove Is* error functions

- Use errors.Is instead of quality comparisons. This is better because it
  matches wrapped errors as well, which we will need later in this branch.
- Inline the errors.Is calls at the call sites. This is idiomatic go, we don't
  need helper functions for this.

See https://go.dev/blog/go1.13-errors for more about this.
2025-06-05 13:20:38 +02:00
Stefan Haller
ac0c3db472
Fix wrong inactive highlight when switching between repos (#4621)
- **PR Description**

When switching between repos, each repo might have a different focused
panel; in this case, the previously focused panel would show the
"inactive" highlight. By default this is only bold text, so it's barely
noticeable, but it becomes more pronounced when setting e.g.

```yml
gui:
  theme:
    inactiveViewSelectedLineBgColor:
      - "#666666"
```

I noticed this especially when entering or leaving submodules; for
example, enter a submodule by pressing enter in the Files panel, then
switch to the Commits panel in the submodule, then press Esc to go back
to the parent repo. This would put the focus back into the Files panel,
but keep the inactive highlight in the Commits panel.
2025-06-05 13:00:54 +02:00
Stefan Haller
f185e1a5e3 Fix wrong inactive highlight when switching between repos
When switching between repos, each repo might have a different focused panel; in
this case, the previously focused panel would show the "inactive" highlight. By
default this is only bold text, so it's barely noticeable, but it becomes more
pronounced when setting e.g.

gui:
  theme:
    inactiveViewSelectedLineBgColor:
      - "#666666"

I noticed this especially when entering or leaving submodules; for example,
enter a submodule by pressing enter in the Files panel, then switch to the
Commits panel in the submodule, then press Esc to go back to the parent repo.
This would put the focus back into the Files panel, but keep the inactive
highlight in the Commits panel.
2025-06-05 12:58:38 +02:00
Stefan Haller
ac7de7e8de
Fix resetting to a branch when a tag shares the same name, or vice versa (#4571)
- **PR Description**

Allows the reset menu to have a different name that is displayed, and a
fully qualified name that git will unambiguously know what it refers
about. We could totally squash this back down to 1 input, and display to
the user the _precise_ full ref name that we are resetting to, but I
think the context they are in (branches tab versus tag tab), means that
we don't need to do that, and can continue to just show the branch name
and the tag name to the end users.

Fixes https://github.com/jesseduffield/lazygit/issues/4569
2025-06-04 20:48:32 +02:00
Chris McDonnell
706891e92b Add integration test for resetting to upstream branch with duplicate name 2025-06-04 20:43:01 +02:00
Chris McDonnell
fa238809ae Use full refname instead of short to prevent disambiguation with tag
In the unlikely scenario that you have a remote branch on `origin` called
`foo`, and a local tag called `origin/foo`, git changes the behavior of
the previous command such that it produces

```
$ git for-each-ref --sort=refname --format=%(refname:short) refs/remotes

origin/branch1
remotes/origin/foo
```

with `remotes/` prepended. Presumably this is to disambiguate it from
the local tag `origin/foo`. Unfortunately, this breaks the existing
behavior of this function, so the remote branch is never shown.

By changing the command, we now get
```
$ git for-each-ref --sort=refname --format=%(refname) refs/remotes

refs/remotes/origin/branch1
refs/remotes/origin/foo
```

This allows easy parsing based on the `/`, and none of the code outside
this function has to change.

----

We previously were not showing remote HEADs for modern git versions
based on how they were formatted from "%(refname:short)".
We have decided that this is a feature, not a bug, so we are building
that into the code here.
2025-06-04 20:43:01 +02:00
Chris McDonnell
737a99b1c8 Add integration tests showing resetting to duplicate named tags and branches 2025-06-04 20:43:01 +02:00
Chris McDonnell
122d6e5f0d Add FullRefName to all reset menus 2025-06-04 20:43:01 +02:00
Stefan Haller
36de219eb7
Show default option when prompting to create a new git repo (#4596) 2025-06-04 08:25:53 +02:00
Joshua Hollander
bb6c883761 Print default option when prompting to create a new git repo 2025-06-04 08:15:21 +02:00
Stefan Haller
1e5d104524
Improve PR template wrt release notes (#4607)
Mention in the PR template that PR titles will be used in release notes.
This came up in #4571.
2025-06-01 14:38:09 +02:00
Stefan Haller
946f5f130c Make PR template mention that PR titles will be used in release notes 2025-06-01 14:34:12 +02:00
Stefan Haller
a8c73f1ff2
Replace literal with ConfigFilename constant (#4613)
A tiny clean-up where I assume it is a good idea to re-use the common
specification of the `"config.yml"` name.
2025-05-31 17:34:06 +02:00
Mateusz Łoskot
d60fe437ef Replace literal with ConfigFilename constant
Signed-off-by: Mateusz Łoskot <mateusz@loskot.net>
2025-05-31 02:28:39 +02:00
Stefan Haller
8280fdedb7
Use branchPrefix when moving commits to new branch (#4604)
- **PR Description**

When pressing N to move new commits to a new branch we get greeted with
an empty prompt, this PR makes it so we fill the empty prompt with a
suggestion taken from branchPrefix, similar to the good old create a new
branch.
2025-05-29 22:42:37 +02:00
Elias Assaf
fdf9726c37 Use branchPrefix on moving commits to a new branch
Signed-off-by: Elias Assaf <elyas51000@gmail.com>
2025-05-29 22:39:26 +02:00
Elias Assaf
816d0c0820 Add a function to suggest a branch name based on branchPrefix
Moving the getter of the suggested branch name to a separate function
allows us to reuse it in situations where we are not calling the regular
create new branch function, such as move commits to a new branch

Signed-off-by: Elias Assaf <elyas51000@gmail.com>
2025-05-29 21:07:22 +03:00
Stefan Haller
5b4d009f55
Fix branch selection jumping back on background fetch (#4597)
- **PR Description**

When refreshing the branches list, we have code to keep the same branch
selected even when the refresh changes the sort order; this code
remembers the selected branch before the refresh, and then tries to
select it again afterwards (looking it up by name) if it is still there.

However, we stored the previously selected branch too early, before even
obtaining the branches list; if the user moved the selection between
that point and the end of the refresh, it would jump back. Fix this by
remembering the previous selection only at the last moment, right before
assigning the new branches slice.

We still have a race condition here between the UI code that manages the
selection as the user presses arrow keys, and the background thread
doing the refresh that reads and restores the selection; however, the
race was there before, and we make it neither better nor worse with this
PR. It doesn't seem to be a problem in practice.

Fixes #4116.
2025-05-29 14:45:09 +02:00
Stefan Haller
fce4816a0d Fix branch selection jumping back on background fetch
When refreshing the branches list, we have code to keep the same branch selected
even when the refresh changes the sort order; this code remembers the selected
branch before the refresh, and then tries to select it again afterwards (looking
it up by name) if it is still there.

However, we stored the previously selected branch too early, before even
obtaining the branches list; if the user moved the selection between that point
and the end of the refresh, it would jump back. Fix this by remembering the
previous selection only at the last moment, right before assigning the new
branches slice.

We still have a race condition here between the UI code that manages the
selection as the user presses arrow keys, and the background thread doing the
refresh that reads and restores the selection; however, the race was there
before, and we make it neither better nor worse with this PR. It doesn't seem to
be a problem in practice.
2025-05-29 14:41:59 +02:00
Stefan Haller
676b5c2287
Kill background fetch when it requests a passphrase (#4588)
Previously we would enter a newline at the password prompt, which would
cause the fetch to fail. The problem with this was that if you have many
remotes, the fetch would sometimes hang for some reason; I don't totally
understand how that happened, but I guess the many ssh processes
requesting passwords would somehow interfere with each other. Avoid this
by simply killing the git fetch process the moment it requests the first
password.
2025-05-29 14:39:39 +02:00
Stefan Haller
d5bd30474c Kill background fetch when it requests a passphrase
Previously we would enter a newline at the password prompt, which would cause
the fetch to fail. The problem with this was that if you have many remotes, the
fetch would sometimes hang for some reason; I don't totally understand how that
happened, but I guess the many ssh processes requesting passwords would somehow
interfere with each other. Avoid this by simply killing the git fetch process
the moment it requests the first password.
2025-05-29 14:36:01 +02:00
Stefan Haller
75a8c0c73e Pass cmdObj instead of task to processOutput
This is a preparation for the next commit, where we will need more from the
cmdObj in processOutput.
2025-05-29 14:36:01 +02:00
Stefan Haller
c4bfdaeaf3
Fix selecting large hunks, and fix problems editing very long commit descriptions (#4589)
See https://github.com/jesseduffield/gocui/pull/80 for details.

Fixes #4470.
2025-05-29 14:35:35 +02:00
Stefan Haller
5dbd91038a Bump gocui
See https://github.com/jesseduffield/gocui/pull/80.

This fixes selecting hunks in the staging view that are longer than the screen.
2025-05-29 14:33:17 +02:00
Stefan Haller
21b8b2827e
Add user config for hiding the root item in the file tree (#4593)
- **PR Description**

In #4346 we added a `/` root item in the Files and CommitFiles panels
whenever there is more than one top-level item. We made it
unconditional, but I promised to add a config as soon as users ask for
being able to disable it. For a while I was able to convince users who
asked for it that it is useful and they don't want to turn it off, but
now there's a [stronger
request](https://github.com/jesseduffield/lazygit/discussions/4590#discussioncomment-13254924)
from someone who refuses to upgrade to the current version, and we don't
want that.

So, add a config option `gui.showRootItemInFileTree` that is true by
default.
2025-05-26 21:18:19 +02:00
Stefan Haller
3cff48437e Add user config gui.addRootItemInFileTree 2025-05-24 18:17:25 +02:00
Stefan Haller
ffb8586795 Pass common.Common to file trees instead of just the Log
We will need a user config in the file tree in the next commit, and passing the
entire common is the easiest way to do that while ensuring hot-reloading when
users change the config while lazygit is running.
2025-05-24 17:56:43 +02:00
Jesse Duffield
da32b59e11
Fix lazygit's UI becoming unresponsive when a background fetch asks for a passphrase (#4586)
Fix a regression introduced with #4525.

This fixes the problem that background fetching makes lazygit hang when
the fetch request needs to prompt for a passphrase. For Mac users who
use the keychain to store their ssh passphrases, this can happen when
lazygit is running while the machine goes to sleep, because macOS looks
the keychain in that case.
v0.51.1
2025-05-23 20:33:22 +10:00
Stefan Haller
2a8ef71e8f Use PTY also with credentialStrategy=FAIL
This is a regression introduced with a199ed1396c; it is important to use a PTY
even with credentialStrategy=FAIL, otherwise the fetch command will spew the
credentials request into the UI and then hang.

This fixes the problem that background fetching makes lazygit hang when the
fetch request needs to prompt for a passphrase. For Mac users who use the
keychain to store their ssh passphrases, this can happen when lazygit is running
while the machine goes to sleep, because macOS looks the keychain in that case.
2025-05-23 11:34:57 +02:00
Stefan Haller
6705428a8d
Fix crash when clicking in the status view (#4567)
- **PR Description**

The status view is not supposed to be focusable right now. (This might
change soon, but for now it isn't.) Pressing '0' on it does nothing.

However, clicking on it would still focus it, because the click handler
in MainViewController assumed that when the clicked view doesn't have
the focus, then its "other" view must have, and we just want to toggle
the focus between the two (like when pressing tab). It didn't take the
possibility into account that the current side panel isn't focusable at
all; if it was, then its SwitchToFocusedMainViewController would have
handled the click.

To fix this, check if the "other" view has the focus before handling the
click, and do nothing otherwise.

This also fixes clicking in the main views of the Worktrees or
Submodules tabs, or any other tabs whose main views are not focusable.

Fixes #4566.
v0.51.0
2025-05-22 14:41:04 +02:00
Stefan Haller
bbd17abc43 Add ContextMgr.NextInStack and use it to access side panel of focused main view
This way we don't have to abuse the parent context mechanism, which isn't meant
for this purpose.
2025-05-22 14:38:40 +02:00
Stefan Haller
12ed50464b Cleanup: pass target context to focusMainView directly
It's a bit silly to pass a window name and then call a function to get the
corresponding context, when we can simply pass the context directly.
2025-05-22 14:38:40 +02:00
Stefan Haller
57991c1da8 Fix crash when clicking in the status view
The click handler of MainViewController was registered as a global handler, so
it was used when a side panel was focused that doesn't have a
SwitchToFocusedMainViewController attached (e.g. Status, Worktrees, or
Submodules). This handler would then push the main view context, but with the
code that is meant only for toggling between the main view pair contexts, i.e.
with taking over the parentContext from the otherContext, which doesn't have one
at that point. This would later lead to a crash in onClick because the
parentContext was nil.

Fix this by splitting the click handler in two, one for when it already has the
focus, and one for toggling from the other view, and make these focus specific.
2025-05-22 14:38:40 +02:00
Stefan Haller
eecb59dd8a
Fix home and end keys in prompts (#4554)
- **PR Description**

In #4404 we added home/end support to confirmation popups. This broke
handling of the home/end keys in prompts, where they used to work as
alternatives to ctrl-a and ctrl-e.

Here's one way (maybe not the best) to fix this.

A better fix might have been to have separate views for confirmations
and prompts, so that we can have different keybindings for each. That's
a bit more work though.

Fixes #4553.
2025-05-22 08:50:45 +02:00
Stefan Haller
b8fcaf01b8 Make home and end keys work in prompts 2025-05-22 08:48:38 +02:00
Stefan Haller
c80b0e1910 Bump gocui 2025-05-22 08:48:14 +02:00
Stefan Haller
f250dfb8de
Fix main view occasionally scrolling to the top on its own when focused (#4573)
Ok, this is a long one. (It took me all weekend to figure out.)

We seem to have a race condition between re-rendering the main view and
the [layout
code](a0ec22c251/pkg/gui/layout.go (L75))
that checks whether a view has become smaller and therefore needs to
scroll up. When rerendering the main view, we are careful not to
invalidate the ViewLines array, so the code first calls Reset on the
view, and then starts writing lines to the view until we have written
enough for its old scroll position, and only then do we trigger a
redraw. This is all well and good, but theoretically it could happen
that the above-mentioned layout code runs shortly after the task has
started writing lines to the view (say, after the first one has been
written), and then it would see that the view's height is only 1, and
scroll it all the way to the top.

I have never seen this happen, so it seems that we are being lucky and
the race condition is only a theoretical one.

However: we had a very silly and embarrassing bug in the
focused-main-view code that triggers the race condition occasionally.
The bug is that when the main view is focused, we would refresh it
multiple times in quick succession, once for every side panel that is
being refreshed (instead of just once for the side panel that it belongs
to). So the first task would call Reset, start writing lines to the
view, and then the second task would come along, kill the first, call
Reset again, and start writing lines again, and so on. Apparently this
made it more likely for the layout code to run concurrently with this,
and see the view at a moment where it only has one or two lines. I have
seen it scroll to the top on its own a few times, which is very annoying
when you are in the middle of reviewing a longer commit, for instance.

We can fix this by refreshing the main view only for the side panel that
it belongs to, which is what this PR does. I have let lazygit run over
night with a `refresher.refreshInterval` value of 3, and it hadn't
scrolled to the top when I came to look in the morning, which makes me
pretty confident that we're good now.

It would still be nice if we could fix the race condition for real too,
but it's less urgent now, and it also doesn't seem trivial. I guess
instead of writing lines directly to the view we would have to buffer
them first, and only write them to the view when the original scroll
position is reached (with some synchronization, e.g. with a OnUIThread).
There are other complications that make this tricky though, and I have
no plans right now to tackle this.
2025-05-22 08:17:19 +02:00
Stefan Haller
f3466e2525 Render the main view only for the side context that it belongs to
Previously we would re-render the focused main view several times during a
refresh, once for every side panel. While this should usually not be noticeable
for users because we are careful to avoid flicker when refreshing the main view,
this would sometimes lead to the main view scrolling up to the top by itself;
see PR description for more details.
2025-05-22 08:15:25 +02:00
Stefan Haller
7a24c5628a
Print migration changes to the console when migrating config file (#4548)
- **PR Description**

This might be useful to see in general (users will normally only see it
after they quit lazygit again, but still). But it is especially useful
when writing back the config file fails; some users have their config
file in a read-only location, so we had reports of lazygit no longer
starting up when migration was necessary. #4210 was supposed to improve
this a bit, but it didn't tell users what changes need to be made to the
config file. Now we tell them, and users can then make these changes
manually if they want.

We do this only at startup, when the GUI hasn't started yet. This is
probably good enough, because it is much less likely that writing back a
migrated repo-local config fails because it is not writeable.

Example output:
```
The user config file /Users/stk/Library/Application Support/lazygit/config.yml must be migrated. Attempting to do this automatically.
The following changes were made:

- Renamed 'gui.windowSize' to 'screenMode'
- Changed 'null' to '<disabled>' for keybinding 'keybinding.universal.confirmInEditor'
- Changed 'stream: true' to 'output: log' in custom command

Config file saved successfully to /Users/stk/Library/Application Support/lazygit/config.yml
```

The branch also contains a lot of code cleanups.

- **Please check if the PR fulfills these requirements**

* [x] Cheatsheets are up-to-date (run `go generate ./...`)
* [x] Code has been formatted (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
* [x] Tests have been added/updated (see
[here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md)
for the integration test guide)
* [ ] Text is internationalised (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
* [ ] If a new UserConfig entry was added, make sure it can be
hot-reloaded (see
[here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig))
* [ ] Docs have been updated if necessary
* [x] You've read through your own file changes for silly mistakes etc
2025-05-21 08:54:55 +02:00
Stefan Haller
cabcd54508 Include migration changes in the error message if we can't log them
This is for the unlikely case that a repo-local config file can't be written
back after migration; in this case we can't log the migration changes to the
console, so include them in the error popup instead.
2025-05-21 08:51:24 +02:00
Stefan Haller
a4f43cb275 Log a list of migration changes to the console
This might be useful to see in general (users will normally only see it after
they quit lazygit again, but still). But it is especially useful when writing
back the config file fails for some reason, because users can then make these
changes manually if they want.

We do this only at startup, when the GUI hasn't started yet. This is probably
good enough, because it is much less likely that writing back a migrated
repo-local config fails because it is not writeable.
2025-05-21 08:51:24 +02:00
Stefan Haller
caa8c921e6 Make RenameYamlKey return a bool 2025-05-21 08:51:24 +02:00
Stefan Haller
48305c18f7 Cleanup: remove redundant if statement 2025-05-21 08:51:24 +02:00
Stefan Haller
ffda51014d Print migration hints only when GUI hasn't started yet
Most migrations happen at startup when loading the global config file, at a time
where the GUI hasn't been initialized yet. We can safely print to the console at
that point. However, it is also possible that repo-local config files need to be
migrated, and this happens when the GUI has already started, at which point we
had better not print anything to stdout; this totally messes up the UI.

In this commit we simply suppress the logging when the GUI is running already.
This is probably good enough, because the logging is mostly useful in the case
that writing back the migrated config file fails, so that users understand
better why lazygit doesn't start up; and this is very unlikely to happen for
repo-local config files, because why would users make them read-only.
2025-05-21 08:51:24 +02:00
Stefan Haller
61822b73f0 Add tests for migrating null keybindings to <disabled> 2025-05-21 08:51:24 +02:00