From 88cf4dd97daa998552649d72354acd9515d80779 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 10 Nov 2026 13:15:34 +0100 Subject: [PATCH] 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 --- .../helpers/working_tree_helper.go | 8 +--- .../commit_in_editor_with_nothing_staged.go | 44 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 pkg/integration/tests/commit/commit_in_editor_with_nothing_staged.go diff --git a/pkg/gui/controllers/helpers/working_tree_helper.go b/pkg/gui/controllers/helpers/working_tree_helper.go index d4a48fa79..ad3dfc4d0 100644 --- a/pkg/gui/controllers/helpers/working_tree_helper.go +++ b/pkg/gui/controllers/helpers/working_tree_helper.go @@ -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) }, }) diff --git a/pkg/integration/tests/commit/commit_in_editor_with_nothing_staged.go b/pkg/integration/tests/commit/commit_in_editor_with_nothing_staged.go new file mode 100644 index 000000000..f48ea3468 --- /dev/null +++ b/pkg/integration/tests/commit/commit_in_editor_with_nothing_staged.go @@ -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"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index ee1ca9a91..6d66a1080 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -145,6 +145,7 @@ var tests = []*components.IntegrationTest{ commit.Commit, commit.CommitAllWithNestedRepository, commit.CommitDuringSquashMerge, + commit.CommitInEditorWithNothingStaged, commit.CommitMultiline, commit.CommitSkipHooks, commit.CommitSwitchToEditor,