From 9f38d02a4e8c227205b31ec1031e5c5e64c85575 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 30 Mar 2026 17:21:45 +0200 Subject: [PATCH] Don't stage out-of-date submodules when asking user to auto-stage after resolving conflicts When you rebase a branch and there are conflicts, lazygit asks you to continue the rebase when it detects that all conflicts have been resolved. However, it is common to make additional changes beyond just fixing the conflicts (e.g. to fix build failures), and when doing that while the "Continue the rebase?" prompt is showing, lazygit detects that too and asks you if you want to stage those newly modified files too. This is all well and good (and can be disabled for those who don't like it); however, lazygit would treat out-of-date submodules as unstaged changes and would offer to stage those as well, and this is pretty bad and almost never what you want. Fix this by excluding submodules from that second check. --- pkg/gui/controllers/helpers/merge_and_rebase_helper.go | 6 +++--- pkg/gui/controllers/helpers/working_tree_helper.go | 6 ++++++ ...conflicts_fix_build_errors_with_out_of_date_submodule.go | 6 ------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go index 7d4f0a96a..7f51bc35d 100644 --- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go +++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go @@ -237,14 +237,14 @@ func (self *MergeAndRebaseHelper) PromptToContinueRebase() error { Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}, }) - root := self.c.Contexts().Files.FileTreeViewModel.GetRoot() - if root.GetHasUnstagedChanges() { + unstagedFiles := GetUnstagedFilesExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) + if len(unstagedFiles) > 0 { self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.Continue, Prompt: self.c.Tr.UnstagedFilesAfterConflictsResolved, HandleConfirm: func() error { self.c.LogAction(self.c.Tr.Actions.StageAllFiles) - if err := self.c.Git().WorkingTree.StageAll(true); err != nil { + if err := self.c.Git().WorkingTree.StageFiles(unstagedFiles, []string{}); err != nil { return err } diff --git a/pkg/gui/controllers/helpers/working_tree_helper.go b/pkg/gui/controllers/helpers/working_tree_helper.go index 94a24e5ee..d6289537b 100644 --- a/pkg/gui/controllers/helpers/working_tree_helper.go +++ b/pkg/gui/controllers/helpers/working_tree_helper.go @@ -97,6 +97,12 @@ func IsWorkingTreeDirtyExceptSubmodules(files []*models.File, submoduleConfigs [ return AnyStagedFilesExceptSubmodules(files, submoduleConfigs) || AnyTrackedFilesExceptSubmodules(files, submoduleConfigs) } +func GetUnstagedFilesExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) []string { + return lo.FilterMap(files, func(f *models.File, _ int) (string, bool) { + return f.Path, f.HasUnstagedChanges && f.Tracked && !f.IsSubmodule(submoduleConfigs) + }) +} + func (self *WorkingTreeHelper) FileForSubmodule(submodule *models.SubmoduleConfig) *models.File { for _, file := range self.c.Model().Files { if file.IsSubmodule([]*models.SubmoduleConfig{submodule}) { diff --git a/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors_with_out_of_date_submodule.go b/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors_with_out_of_date_submodule.go index 22fbfdb5f..1b95fd316 100644 --- a/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors_with_out_of_date_submodule.go +++ b/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors_with_out_of_date_submodule.go @@ -90,12 +90,9 @@ var RebaseConflictsFixBuildErrorsWithOutOfDateSubmodule = NewIntegrationTest(New t.Views().Files(). Lines( - /* EXPECTED: Equals("▼ /").IsSelected(), Equals(" M submodule (submodule)"), Equals(" ?? untracked-file"), - ACTUAL: */ - Equals("?? untracked-file"), ) t.Views().Commits(). @@ -109,10 +106,7 @@ var RebaseConflictsFixBuildErrorsWithOutOfDateSubmodule = NewIntegrationTest(New t.Views().Main(). Content( - /* EXPECTED: DoesNotContain("submodule").DoesNotContain("untracked-file"), - ACTUAL: */ - Contains("submodule").DoesNotContain("untracked-file"), ) }, })