Wait for the files refresh before committing after staging all files

If you commit with shift-C ("Commit changes using git editor") while no
files are staged, lazygit asks whether to stage all files. Confirming
this often fails with "fatal: Unable to create '.../.git/index.lock':
File exists".

After staging the files, we refresh the files view and then retry the
commit right away. The refresh runs `git status` on a worker. Since it
is a foreground refresh, git takes index.lock to write its refreshed
stat cache back to the index. So `git commit` can start while the status
command still holds the lock. Committing with `c` doesn't run into this
in practice, because the refresh is done long before the user has typed
a commit message.

Retry the commit in the refresh's Then instead. We already do this when
gui.skipNoStagedFilesWarning is on.

Without the fix, the new test failed in two of six runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-11-10 13:15:34 +01:00
co-authored by Claude Opus 5.5
parent 668f4032da
commit 88cf4dd97d
3 changed files with 46 additions and 7 deletions
@@ -300,13 +300,7 @@ func (self *WorkingTreeHelper) promptToStageAllAndRetry(retry func() error) erro
Title: self.c.Tr.NoFilesStagedTitle,
Prompt: self.c.Tr.NoFilesStagedPrompt,
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.StageAllFiles)
if err := self.c.Git().WorkingTree.StageAll(false); err != nil {
return err
}
self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}})
return retry()
return self.stageAllAndThen(retry)
},
})
@@ -0,0 +1,44 @@
package commit
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var CommitInEditorWithNothingStaged = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Commit using the git editor with nothing staged, confirming to stage all files",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Gui.ShowFileTree = false
},
SetupRepo: func(shell *Shell) {
shell.EmptyCommit("first commit")
shell.CreateFile("file1", "file1 content")
shell.CreateFile("file2", "file2 content")
shell.SetConfig("core.editor", "sh -c 'echo my commit message >.git/COMMIT_EDITMSG'")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().
IsFocused().
Lines(
Equals("?? file1").IsSelected(),
Equals("?? file2"),
).
Press(keys.Files.CommitChangesWithEditor).
Tap(func() {
t.ExpectPopup().Confirmation().
Title(Equals("No files staged")).
Content(Equals("You have not staged any files. Commit all files?")).
Confirm()
}).
IsEmpty()
t.Views().Commits().
Lines(
Contains("my commit message"),
Contains("first commit"),
)
},
})
+1
View File
@@ -145,6 +145,7 @@ var tests = []*components.IntegrationTest{
commit.Commit,
commit.CommitAllWithNestedRepository,
commit.CommitDuringSquashMerge,
commit.CommitInEditorWithNothingStaged,
commit.CommitMultiline,
commit.CommitSkipHooks,
commit.CommitSwitchToEditor,