为什么 Windows 版 Git 会创建我无法从命令行删除的存储库?

为什么 Windows 版 Git 会创建我无法从命令行删除的存储库?

我刚刚“重置”了 Windows 10 的安装。我安装了 Git 的“Git for Windows”发行版https://git-scm.org/

init如果我以任何方式(无论是还是)创建 git 存储库clone,都无法使用命令行提示符从我的文件系统中删除该存储库。我必须使用 Windows 资源管理器来执行此操作。

以下是一个示例会话:

PS C:\Users\radix> mkdir foo


    Directory: C:\Users\radix


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        5/10/2018   5:46 PM                foo


PS C:\Users\radix> cd foo
PS C:\Users\radix\foo> git init .
Initialized empty Git repository in C:/Users/radix/foo/.git/
PS C:\Users\radix\foo> cd ..
PS C:\Users\radix> rm foo -Recurse
rm : Cannot remove item C:\Users\radix\foo\.git: You do not have sufficient access rights to perform this operation.
At line:1 char:1
+ rm foo -Recurse
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (.git:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand
rm : Directory C:\Users\radix\foo cannot be removed because it is not empty.
At line:1 char:1
+ rm foo -Recurse
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (C:\Users\radix\foo:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : DirectoryNotEmpty,Microsoft.PowerShell.Commands.RemoveItemCommand

这是以我的普通用户身份运行的 PowerShell。即使我以管理员身份运行 Powershell,命令rm -Recurse仍然会以完全相同的方式失败。我知道删除这个新foo目录的唯一方法是通过 Windows 资源管理器进行删除,它甚至不会抱怨或提示权限 - 它只是默默地删除它,没有任何问题。

我不认为这是一个特定于 PowerShell 的问题,因为在 CMD 中也会发生类似的行为:

C:\Users\radix>dir foo
 Volume in drive C is Blade
 Volume Serial Number is B83C-EF1B

 Directory of C:\Users\radix

File Not Found

C:\Users\radix>git init foo
Initialized empty Git repository in C:/Users/radix/foo/.git/

C:\Users\radix>del foo
C:\Users\radix\foo\*, Are you sure (Y/N)? y

C:\Users\radix>dir foo
 Volume in drive C is Blade
 Volume Serial Number is B83C-EF1B

 Directory of C:\Users\radix\foo

05/17/2018  08:46 PM    <DIR>          .
05/17/2018  08:46 PM    <DIR>          ..
               0 File(s)              0 bytes
               2 Dir(s)  275,911,991,296 bytes free

C:\Users\radix>dir /a foo
 Volume in drive C is Blade
 Volume Serial Number is B83C-EF1B

 Directory of C:\Users\radix\foo

05/17/2018  08:46 PM    <DIR>          .
05/17/2018  08:46 PM    <DIR>          ..
05/17/2018  08:46 PM    <DIR>          .git
               0 File(s)              0 bytes
               3 Dir(s)  275,866,763,264 bytes free

DEL 命令没有显示任何错误,但它实际上无法删除存储库。

值得注意的是,该rm命令确实会删除文件来自存储库,包括目录内的文件.git。但它留下了.git目录保留在那里。

有人认为.git子目录的“隐藏”性质导致了问题。以下是我对此进行的实验的记录:

PS C:\Users\radix> git init foo
Initialized empty Git repository in C:/Users/radix/foo/.git/

此时,我打开 Windows 资源管理器并导航到C:/Users/radix/foo目录,然后重命名.gitgit。我还右键单击.git目录并打开“属性”对话框,注意到它没有“隐藏”标志。我还导航到git目录并在几个子目录和文件上单击鼠标右键并打开属性,注意到它们都没有设置“隐藏”标志。

然后我尝试从 powershell 删除目录:

PS C:\Users\radix> del foo

Confirm
The item at C:\Users\radix\foo has children and the Recurse parameter was not specified. If you continue, all children
will be removed with the item. Are you sure you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): a
del : Cannot remove item C:\Users\radix\foo\git: You do not have sufficient access rights to perform this operation.
At line:1 char:1
+ del foo
+ ~~~~~~~
    + CategoryInfo          : PermissionDenied: (git:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand
del : Directory C:\Users\radix\foo cannot be removed because it is not empty.
At line:1 char:1
+ del foo
+ ~~~~~~~
    + CategoryInfo          : WriteError: (C:\Users\radix\foo:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : DirectoryNotEmpty,Microsoft.PowerShell.Commands.RemoveItemCommand

我确实注意到此层次结构中的几个文件夹被标记为“只读”。这有关系吗?

所以我有两个问题:为什么我不能删除这个文件夹,为什么 git 首先以一种无法删除的方式创建它? 如果问题是目录是只读的,为什么 git 将它们创建为只读的?

答案1

我先从比较简单的情况开始:del cmd 永远不会执行你想要的操作,因为它只会删除文件。即使这样,没有/s它也不会递归并且只会删除顶级目录中的文件。

因此,对于 cmd,您应该使用rmdir /s它来递归删除所有文件和文件夹。/q如果您想禁用确认提示,请添加。


现在,PowerShell。Remove-Item(它是它的rm别名del-Recurse不会递归到隐藏目录,因此不会删除其内容。这会导致您的错误 - 不是“权限被拒绝”,而是“目录不为空”。

为了解决这个问题,您可以传递-Force参数(相当于 *nix -f)。所以rm -r -force或者Remove-Item -Recurse -Force应该可以工作。

我不完全清楚你是如何获得非隐藏.git目录的 - GfW(诚然是较旧的 2.9.2)为我创建了隐藏目录。在 cmd 中,运行attrib .git以检查它是否被隐藏。一旦取消隐藏,Remove-Item -Recurse无需 即可工作-Force

相关内容