From 98ca24de23f92a6ce161f0a8e004328beb1b89b6 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sat, 7 Nov 2026 23:46:56 +0100 Subject: [PATCH] Delete the right git dir when removing a submodule in a linked worktree Removing a submodule in a linked worktree deletes the git dir of that submodule in the main worktree. This breaks the submodule there, and any unpushed commits, local branches and stashes in it are lost. The git dir of the submodule in the linked worktree stays behind. Git keeps the git dirs of submodules separately for each worktree. For a linked worktree, they are in .git/worktrees//modules. Lazygit used the worktree's git dir until 3b723282cb switched it to the repo's git dir, so this has been broken since v0.41.0. Use the worktree's git dir again. Co-Authored-By: Claude Opus 5.5 --- pkg/commands/git_commands/submodule.go | 5 ++--- pkg/commands/models/submodule_config.go | 6 +++--- .../tests/submodule/remove_in_linked_worktree.go | 4 ---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/pkg/commands/git_commands/submodule.go b/pkg/commands/git_commands/submodule.go index 0fa5de9df..79d3e2318 100644 --- a/pkg/commands/git_commands/submodule.go +++ b/pkg/commands/git_commands/submodule.go @@ -269,9 +269,8 @@ func (self *SubmoduleCommands) Delete(submodule *models.SubmoduleConfig) error { self.Log.Error(err) } - // We may in fact want to use the repo's git dir path but git docs say not to - // mix submodules and worktrees anyway. - return os.RemoveAll(submodule.GitDirPath(self.repoPaths.repoGitDirPath)) + // Git keeps the git dirs of submodules separately for each worktree + return os.RemoveAll(submodule.GitDirPath(self.repoPaths.WorktreeGitDirPath())) } func (self *SubmoduleCommands) Add(name string, path string, url string) error { diff --git a/pkg/commands/models/submodule_config.go b/pkg/commands/models/submodule_config.go index 7df0d131a..48d838ff4 100644 --- a/pkg/commands/models/submodule_config.go +++ b/pkg/commands/models/submodule_config.go @@ -38,10 +38,10 @@ func (r *SubmoduleConfig) Description() string { return r.RefName() } -func (r *SubmoduleConfig) GitDirPath(repoGitDirPath string) string { - parentPath := repoGitDirPath +func (r *SubmoduleConfig) GitDirPath(worktreeGitDirPath string) string { + parentPath := worktreeGitDirPath if r.ParentModule != nil { - parentPath = r.ParentModule.GitDirPath(repoGitDirPath) + parentPath = r.ParentModule.GitDirPath(worktreeGitDirPath) } return filepath.Join(parentPath, "modules", r.Name) diff --git a/pkg/integration/tests/submodule/remove_in_linked_worktree.go b/pkg/integration/tests/submodule/remove_in_linked_worktree.go index 438416894..f081faa46 100644 --- a/pkg/integration/tests/submodule/remove_in_linked_worktree.go +++ b/pkg/integration/tests/submodule/remove_in_linked_worktree.go @@ -42,11 +42,7 @@ var RemoveInLinkedWorktree = NewIntegrationTest(NewIntegrationTestArgs{ IsEmpty() t.FileSystem(). - /* EXPECTED: PathPresent(mainGitDirSubmodulePath). PathNotPresent(linkedGitDirSubmodulePath) - ACTUAL: */ - PathNotPresent(mainGitDirSubmodulePath). - PathPresent(linkedGitDirSubmodulePath) }, })