@@ -1014,7 +1014,25 @@ private void NotifyNewFileCreatedHandler(
10141014 GitCommandLineParser gitCommand = new GitCommandLineParser ( this . Context . Repository . GVFSLock . GetLockedGitCommand ( ) ) ;
10151015 if ( gitCommand . IsValidGitCommand )
10161016 {
1017- this . MarkDirectoryAsPlaceholder ( virtualPath , triggeringProcessId , triggeringProcessImageFileName ) ;
1017+ // When git recreates a directory that was previously deleted (and is
1018+ // tracked in ModifiedPaths), skip marking it as a ProjFS placeholder.
1019+ // Otherwise ProjFS would immediately project all children into it,
1020+ // conflicting with git's own attempt to populate the directory.
1021+ //
1022+ // This check is safe from races with the background task that updates
1023+ // ModifiedPaths: the deletion happens from a non-git process (e.g.,
1024+ // rmdir), and IsReadyForExternalAcquireLockRequests() blocks git from
1025+ // acquiring the GVFS lock until the background queue is drained. When
1026+ // git itself deletes a folder, the code takes the IsValidGitCommand
1027+ // path in OnWorkingDirectoryFileOrFolderDeleteNotification and calls
1028+ // OnPossibleTombstoneFolderCreated instead of OnFolderDeleted, so
1029+ // ModifiedPaths is not involved.
1030+ //
1031+ // See https://github.com/microsoft/VFSForGit/issues/1901
1032+ if ( ! this . FileSystemCallbacks . IsPathOrParentInModifiedPaths ( virtualPath , isFolder : true ) )
1033+ {
1034+ this . MarkDirectoryAsPlaceholder ( virtualPath , triggeringProcessId , triggeringProcessImageFileName ) ;
1035+ }
10181036 }
10191037 else
10201038 {
0 commit comments