Skip to content

Recent repos menu can't return to a repo opened with --git-dir/--work-tree (dotfile repos) #5942

Description

@xooooooooox

Describe the bug

The recent repositories menu (ctrl+r) cannot bring you back to a dotfile-style repo — one whose git dir doesn't live at <work tree>/.git, opened with --git-dir/--work-tree (yadm) or found through core.worktree (vcsh). #5910 fixed this class of problem for the in-session repo-path stack (entering/escaping submodules), but the persistent recent-repos list still only stores paths, so such a repo effectively falls out of repo switching:

  1. The entry disappears from the menu. newRecentReposList (pkg/gui/recent_repos_panel.go) keeps an entry only if <path>/.git exists. A dotfile repo's work tree has no .git, so the next time lazygit runs in any other repo, the entry is dropped from the list.
  2. Even when the entry is still there, switching fails. The menu's OnPress calls switchTo(path), which clears GIT_DIR/GIT_WORK_TREE and chdirs to the path; VerifyInGitRepo then fails with "must be run inside a repository", because nothing at the work tree's path leads to the git dir.
  3. The root cause is that AppState.RecentRepos is []string — there is nowhere to remember how the repo was found. The old comment in updateRecentRepoList ("we could totally do this but it would require storing both the git-dir and the worktree in our recent repos list, which is a change that would need to be backwards compatible", from e873816, 2020) describes exactly this gap; Fix several problems with repos whose git dir lives outside the working tree #5910's RepoLocation.GitLocationEnvVars now provides the mechanism, the recent-repos list is just not wired up to it.

The startup path has the same blind spot: openRecentRepo in pkg/app/app.go checks <path>/.git and silently skips dotfile repos when offering to open the most recent repo.

To reproduce

mkdir -p ~/tmp/project/repo && cd ~/tmp/project/repo
git init --bare ../.bare
git --git-dir=../.bare --work-tree=. checkout -b main
touch blah && git --git-dir=../.bare --work-tree=. add blah
git --git-dir=../.bare --work-tree=. commit -m 'initial commit'

lazygit --git-dir=$PWD/../.bare --work-tree=$PWD
# ctrl+r, switch to any previously visited normal repo — this works
# ctrl+r again — the dotfile repo is not in the menu anymore
# (on older state where the entry still exists, selecting it errors instead)

Expected behavior

Switching away from a dotfile repo and back again through the recent repositories menu round-trips, the same way entering and escaping a submodule now does after #5910.

Notes on a possible fix

I have a working patch on a fork branch, linked purely as a reference — I've read CONTRIBUTING.md and I'm not posting a PR: https://github.com/xooooooooox/lazygit/tree/fix-recent-repos-git-location

It adds RecentRepoGitLocations map[string][]string to AppState alongside RecentRepos (backwards compatible in both directions — old binaries ignore the unknown key, new binaries tolerate its absence), records RepoPaths.GitLocationEnvVars() in updateRecentRepoList, relaxes the .git existence filter to also accept entries with a recorded git dir, and has the menu switch through switchToLocation with the recorded env vars. The IsBareRepo() early-out can then also be narrowed to bare repos without a work tree, which resolves the 2020 comment. Covered by two integration tests (--git-dir+--work-tree and core.worktree flavours).

Version info

Reproduced on master (c199ac6) and v0.64.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions