Почему Git для Windows создает репозитории, которые я не могу удалить из командной строки?

5

У меня недавно была «Сброс» установки Windows 10. Я установил дистрибутив Git «Git для Windows» с https://git-scm.org/ .

Если я создаю git-репозиторий каким-либо образом (будь то initили clone), этот репозиторий нельзя удалить из моей файловой системы с помощью командной строки. Я должен использовать Windows Explorer, чтобы сделать это.

Вот пример сеанса:

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каталог и переименовываюсь .gitв git. Я также щелкаю правой кнопкой мыши по .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 создает их только для чтения?

Кристофер Армстронг
источник
Какую ошибку вы получили при удалении каталога из командной строки (CMD)? Хотя я получаю ту же ошибку при удалении из PowerShell, я не получаю никакой ошибки при удалении из CMD.
PetSerAl
Дальнейшие исследования показывают, что проблема вызвана тем, что .gitкаталог скрыт и Remove-Itemотказывается от его удаления, если не указан -Forceпараметр.
PetSerAl
Я не верю, что скрытая природа .git влияет на вещи вообще. Когда я удаляю атрибут «Hidden» из .git (и всех элементов рекурсивно) и переименовываю его в «git», поведение остается тем же.
Кристофер Армстронг
Вы пробовали другую папку, кроме C:\User\user_name? Также попробуйте с помощью git в cygwin (т.е. установите cygwin, откройте установку cygwin, установите git).
Бисваприйо
@Biswapriyo мой вопрос специально и намеренно о Git для Windows. и да, я пробовал это в каталогах, таких как ~ / Documents и подкаталогах ~ / AppData / Local.
Кристофер Армстронг

Ответы:

7

Начну с более простого случая: 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.

боб
источник
Git для Windows создается .gitкак скрытый. В одной из моих расшифровок я описал, как переименование его gitи обеспечение его скрытности не решает проблему в powershell. Я добавил этот раздел в ответ на некоторые комментарии к моему первоначальному вопросу.
Кристофер Армстронг
@ChristopherArmstrong Работает для меня после сброса скрытого ... попробуйте еще раз с просто Remove-Item -Recurse. И попробуйте -Forceвариант, не отключая скрытый.
Боб
Я обнаружил проблему: дело не только в том, что .gitкаталог имеет Hатрибут, но и в том, что файлы пакета .git/objects/packимеют Rатрибут (только для чтения). Как только я удалю эти атрибуты, я смогу, наконец, удалить git-репо -Force.
Кристофер Армстронг