@@ -174,10 +174,28 @@ public static ScopedFileSystem ScopeSourceDirectoryForWrite(IFileSystem inner, s
174174 /// </summary>
175175 public static ScopedFileSystem RealGitRootForPath ( string ? path )
176176 {
177- if ( path is null )
177+ var root = path is null ? Paths . WorkingDirectoryRoot . FullName : Paths . FindGitRoot ( path ) ;
178+ var roots = new List < string > { root , Paths . ApplicationData . FullName } ;
179+
180+ // In a git worktree the local .git entry is a file pointing to the main repo's
181+ // .git/worktrees/<name> directory. GitCheckoutInformation needs to read config and
182+ // HEAD from the main repo's .git dir, which lives outside the worktree root.
183+ // Add it as an explicit scope root so those reads are not rejected.
184+ var worktreePointer = Path . Join ( root , ".git" ) ;
185+ if ( File . Exists ( worktreePointer ) )
186+ {
187+ var gitdir = File . ReadAllText ( worktreePointer ) . Replace ( "gitdir:" , "" ) . Trim ( ) ;
188+ // gitdir = /main/repo/.git/worktrees/<name> — go up two levels to reach .git
189+ var mainGitDir = Path . GetFullPath ( Path . Join ( gitdir , ".." , ".." ) ) ;
190+ if ( Directory . Exists ( mainGitDir ) )
191+ roots . Add ( mainGitDir ) ;
192+ }
193+
194+ // Fast path: no worktree detected and path was null — reuse the pre-built instance
195+ if ( roots . Count == 2 && path is null )
178196 return RealRead ;
179- var root = Paths . FindGitRoot ( path ) ;
180- return new ScopedFileSystem ( new FileSystem ( ) , new ScopedFileSystemOptions ( [ root , Paths . ApplicationData . FullName ] )
197+
198+ return new ScopedFileSystem ( new FileSystem ( ) , new ScopedFileSystemOptions ( [ .. roots ] )
181199 {
182200 AllowedHiddenFolderNames = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) { ".git" , ".artifacts" } ,
183201 AllowedHiddenFileNames = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) { ".git" , ".doc.state" }
0 commit comments