diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index dafcea34b336ae..8ac6936191a3be 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -477,12 +477,23 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi .filter(repository => !!repository) as Repository[]; const activeRepositories = new Set(activeRepositoriesList); - const openRepositoriesToDispose = removed - .map(folder => this.getOpenRepository(folder.uri)) - .filter(r => !!r) - .filter(r => !activeRepositories.has(r!.repository)) - .filter(r => !(workspace.workspaceFolders || []).some(f => isDescendant(f.uri.fsPath, r!.repository.root))) as OpenRepository[]; + // A repository may be rooted at, inside, or ABOVE a workspace folder + // (for example, when git.openRepositoryInParentFolders is enabled). + const overlapsFolder = (folderPath: string, repositoryRoot: string): boolean => + pathEquals(folderPath, repositoryRoot) || + isDescendant(folderPath, repositoryRoot) || + isDescendant(repositoryRoot, folderPath); + + const remainingFolders = workspace.workspaceFolders || []; + const openRepositoriesToDispose = this.openRepositories + .filter(r => removed.some(folder => overlapsFolder(folder.uri.fsPath, r.repository.root))) + .filter(r => !activeRepositories.has(r.repository)) + // Keep a parent repo open while any remaining child workspace folder uses it. + .filter(r => !remainingFolders.some(folder => overlapsFolder(folder.uri.fsPath, r.repository.root))); + + // Manually closed repository markers are intentionally kept so that the + // repository scan below does not reopen a repository the user closed. openRepositoriesToDispose.forEach(r => r.dispose()); this.logger.trace(`[Model][onDidChangeWorkspaceFolders] Workspace folders: [${possibleRepositoryFolders.map(p => p.uri.fsPath).join(', ')}]`); await Promise.all(possibleRepositoryFolders.map(p => this.openRepository(p.uri.fsPath)));