Fix crash when two worktrees have the same path

If a linked worktree's directory is deleted and another worktree is
moved to the same path, `git worktree list` reports both worktrees with
that path. lazygit then crashes at startup with a stack overflow, and
the terminal is left in a broken state.

To tell the paths in a group apart, getUniqueNamesFromPathsAux keeps
looking at one more parent directory, but identical paths never come
apart, so it recurses forever. A stack overflow is a fatal error rather
than a panic. No deferred function runs, so the terminal is not
restored either.

Name identical paths like a single path instead of recursing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-10-15 08:35:00 +02:00
co-authored by Claude Opus 5.5
parent 29e8c79ff5
commit ebee95b847
2 changed files with 32 additions and 3 deletions
+10 -3
View File
@@ -236,9 +236,16 @@ func getUniqueNamesFromPathsAux(paths []pathWithIndexT, depth int) []nameWithInd
result := []nameWithIndexT{}
for _, group := range groups {
if len(group) == 1 {
path := group[0]
result = append(result, nameWithIndexT{index: path.index, name: sliceAtDepth(path.path, depth)})
// Identical paths can't be told apart at any depth, so they are named
// like a single path. Git reports two worktrees with the same path when
// a worktree directory was deleted and another worktree was moved to
// its place.
if lo.EveryBy(group, func(path pathWithIndexT) bool {
return trimSlashes(path.path) == trimSlashes(group[0].path)
}) {
for _, path := range group {
result = append(result, nameWithIndexT{index: path.index, name: sliceAtDepth(path.path, depth)})
}
} else {
result = append(result, getUniqueNamesFromPathsAux(group, depth+1)...)
}
@@ -353,6 +353,28 @@ func TestGetUniqueNamesFromPaths(t *testing.T) {
"e/c/d",
},
},
{
input: []string{
"/a/b/c",
"/a/b/c",
},
expected: []string{
"c",
"c",
},
},
{
input: []string{
"/a/b/c",
"/a/b/c/",
"/a/d/c",
},
expected: []string{
"b/c",
"b/c",
"d/c",
},
},
} {
actual := getUniqueNamesFromPaths(scenario.input)
assert.EqualValues(t, scenario.expected, actual)