git: discover worktrees when opening a worktree directory (#264209)#309321
git: discover worktrees when opening a worktree directory (#264209)#309321marcelsafin wants to merge 1 commit intomicrosoft:mainfrom
Conversation
📬 CODENOTIFYThe following users are being notified based on files changed in this PR: @lszomoruMatched files:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes Git worktree discovery when opening a worktree directory (instead of the main repository) with git.detectWorktrees enabled, ensuring worktree management commands become available by auto-opening the main repo and sibling worktrees.
Changes:
- Update worktree auto-discovery logic to consider sibling worktrees + main repo when the opened repository is itself a worktree.
- Adjust worktree candidate selection to exclude the currently-open worktree from auto-open candidates.
- Remove/replace a confusing trace message related to worktree detection skipping.
extensions/git/src/model.ts
Outdated
| // When a worktree is opened, discover sibling worktrees and the | ||
| // main repository so that worktree management commands are available. | ||
| const candidateWorktrees = repository.kind === 'worktree' | ||
| ? repository.worktrees.filter(w => !pathEquals(w.path, repository.root)) | ||
| : repository.worktrees; |
There was a problem hiding this comment.
repository.worktrees includes the main worktree entry (path == repository.root) for non-bare repos (see git.ts#getWorktreesFS), so when repository.kind !== 'worktree' this code still counts/opens the current repository as a candidate worktree. This can cause an off-by-one vs detectWorktreesLimit (warning shown too early and one fewer sibling worktree opened) and triggers an unnecessary self-scan. Consider filtering out the current repo path for all kinds (e.g. repository.worktrees.filter(w => !pathEquals(w.path, repository.root))) rather than only when kind === 'worktree'.
| // When a worktree is opened, discover sibling worktrees and the | |
| // main repository so that worktree management commands are available. | |
| const candidateWorktrees = repository.kind === 'worktree' | |
| ? repository.worktrees.filter(w => !pathEquals(w.path, repository.root)) | |
| : repository.worktrees; | |
| // Discover additional worktrees for the repository, but do not | |
| // include the currently opened repository itself. | |
| const candidateWorktrees = repository.worktrees | |
| .filter(w => !pathEquals(w.path, repository.root)); |
2557225 to
37e9a50
Compare
|
@microsoft-github-policy-service agree |
extensions/git/src/model.ts
Outdated
| if (repository.worktrees.length > worktreesLimit) { | ||
| window.showWarningMessage(l10n.t('The "{0}" repository has {1} worktrees which won\'t be opened automatically. You can still open each one individually by opening a file within.', path.basename(repository.root), repository.worktrees.length)); | ||
| if (candidateWorktrees.length > worktreesLimit) { | ||
| window.showWarningMessage(l10n.t('The "{0}" repository has {1} worktrees which won\'t be opened automatically. You can still open each one individually by opening a file within.', path.basename(repository.root), candidateWorktrees.length)); |
There was a problem hiding this comment.
The warning message says the repository "has {1} worktrees which won't be opened automatically", but the code still opens the first worktreesLimit entries (slice(0, worktreesLimit)). This makes the message/count misleading; consider either reporting the number that will not be opened (e.g. candidateWorktrees.length - worktreesLimit) or rewording to indicate only the first N will be opened automatically.
| window.showWarningMessage(l10n.t('The "{0}" repository has {1} worktrees which won\'t be opened automatically. You can still open each one individually by opening a file within.', path.basename(repository.root), candidateWorktrees.length)); | |
| window.showWarningMessage(l10n.t('The "{0}" repository has {1} worktrees which won\'t be opened automatically. You can still open each one individually by opening a file within.', path.basename(repository.root), candidateWorktrees.length - worktreesLimit)); |
When a worktree directory is opened with `git.detectWorktrees` enabled, `checkForWorktrees()` previously returned early without discovering the main repository or sibling worktrees. This left worktree management commands non-functional because: - Commands like "Create Worktree" filter for repository/submodule kind - "Open Worktree" requires gitOpenRepositoryCount > 1 - SCM menu items depend on a repository-kind provider being open Remove the early return for worktree-kind repositories and instead always filter out the current repository from the candidate list. This enables bidirectional worktree discovery (worktree → main repo, and main repo → worktrees) and also fixes a pre-existing off-by-one in the limit/warning logic where the main repo counted itself as a candidate. The existing `isRepositoryOutsideWorkspace()` check already allows this because it recognizes paths that appear in any open repository's worktree list, and `getRepositoryExact()` prevents duplicate/recursive opens. Also fixes a confusing log message that said detection "is not skipped" when it was in fact skipping. Fixes microsoft#264209 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
37e9a50 to
dbc73f7
Compare
Summary
When a worktree directory is opened with
git.detectWorktreesenabled,checkForWorktrees()previously returned early without discovering the main repository or sibling worktrees. This left worktree management commands non-functional.Fixes #264209
The Problem
Opening a worktree directory (rather than the main repository) over Remote-SSH with
git.detectWorktrees: trueresults in no worktree commands being available because:checkForWorktrees()bails out immediately whenrepository.kind === "worktree"repositoryFilter: ["repository", "submodule"]) find no matching repositorygitOpenRepositoryCount > 1— not met with only 1 reposcmProviderContext == "repository"are hiddenThe Fix
Remove the early return for worktree-kind repositories and always filter out the current repository from the worktree candidate list via
pathEquals(w.path, repository.root). This:repository.worktrees, wasting a slot indetectWorktreesLimitand triggering the "too many worktrees" warning one entry too earlySafety guarantees:
getRepositoryExact()short-circuits when a repo is already openisRepositoryOutsideWorkspace()already recognizes paths in any open repository's worktree list (model.ts L1130-1136)getWorktreesFS()excludes the main worktree entry for bare reposworktreesis empty on first call but populated afteronDidRunGitStatus, which re-triggerscheckForWorktrees()Also fixes a confusing log message that said detection "is not skipped" when it was in fact skipping.