¿Por qué Git para Windows crea repositorios que no puedo eliminar de una línea de comandos?

5

Recientemente he "restablecido" la instalación de Windows 10. Instalé la distribución "Git para Windows" de Git desde https://git-scm.org/ .

Si creo un repositorio git de alguna manera (ya sea inito no clone), ese repositorio no se puede eliminar de mi sistema de archivos con un indicador de línea de comandos. Tengo que usar el Explorador de Windows para hacerlo.

Aquí hay una sesión de muestra:

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

Este es PowerShell ejecutándose como mi usuario normal. Incluso si ejecuto Powershell como administrador, el rm -Recursecomando todavía falla exactamente de la misma manera. La única forma en que sé eliminar este nuevo foodirectorio es hacerlo a través del Explorador de Windows, que ni siquiera se queja ni solicita permisos, simplemente lo elimina silenciosamente sin ningún problema.

No creo que este sea un problema específico de PowerShell, porque ocurre un comportamiento similar en 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

El comando DEL no muestra ningún error, pero no puede eliminar realmente el repositorio.

Es importante tener en cuenta que el rmcomando elimina los archivos del repositorio, incluidos los archivos dentro del .gitdirectorio. Pero deja el .gitdirectorio allí.

Se ha postulado que la naturaleza "oculta" del .gitsubdirectorio está causando un problema. Aquí hay una transcripción de mi experimentación con respecto a eso:

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

En este punto, abro el Explorador de Windows y navego al C:/Users/radix/foodirectorio, y cambio el nombre .gita git. También hago clic derecho en el .gitdirectorio y abro el cuadro de diálogo Propiedades, notando que no tiene la bandera "oculta". También navego en el gitdirectorio y hago clic con el botón derecho en abrir-propiedades en varios subdirectorios y archivos, notando que ninguno de ellos tiene el conjunto de banderas "Oculto".

Y luego trato de eliminar el directorio de 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

Me doy cuenta de que varias de las carpetas de esta jerarquía están marcadas como "Solo lectura". ¿Eso está relacionado?

Entonces tengo dos preguntas: ¿por qué no puedo eliminar esta carpeta y por qué git la crea de una manera que no se puede eliminar en primer lugar? Si el problema es que los directorios son de solo lectura, ¿por qué git los crea como de solo lectura?

Christopher Armstrong
fuente
¿Qué error obtuvo al eliminar el directorio del símbolo del sistema (CMD)? Si bien obtengo el mismo error al eliminar de PowerShell, no recibo ningún error al eliminarlo de CMD.
PetSerAl
La investigación adicional muestra que el problema está causado por el hecho de que el .gitdirectorio está oculto y se Remove-Itemniega a eliminarlo, a menos que especifique el -Forceparámetro.
PetSerAl
No creo que la naturaleza oculta de .git esté afectando las cosas en absoluto. Cuando elimino el atributo "Oculto" de .git (y todos los elementos de forma recursiva) y le cambio el nombre a "git", el comportamiento es el mismo.
Christopher Armstrong
¿Intentaste otra carpeta excepto C:\User\user_name? Pruebe también con git en cygwin (es decir, instale cygwin, abra la configuración de cygwin, instale git).
Biswapriyo
@Biswapriyo mi pregunta es específica e intencional sobre Git para Windows. y sí, lo he intentado en directorios como ~ / Documentos y subdirectorios de ~ / AppData / Local.
Christopher Armstrong

Respuestas:

7

Comenzaré abordando el caso más fácil: delen cmd nunca hará lo que desea, porque solo elimina archivos . Incluso entonces, sin /sella no se repetirá y solo eliminará archivos en el directorio de nivel superior.

Entonces, para cmd, debe usar rmdir /spara eliminar recursivamente todos los archivos y carpetas. Agregue /qsi desea deshabilitar la solicitud de confirmación.


Ahora, PowerShell. Remove-Item(que es qué rmy delalias) simplemente -Recurseno volverá a aparecer en directorios ocultos y, por lo tanto, no eliminará su contenido. Lo que conduce a su error, que no es un "permiso denegado" sino más bien un "directorio no vacío".

Para evitar esto, puede pasar el -Forceparámetro (equivalente a * nix -f). Entonces rm -r -forceo Remove-Item -Recurse -Forcedebería funcionar.

No estoy completamente seguro de cómo está obteniendo un .gitdirectorio no oculto : GfW (ciertamente un 2.9.2 anterior) los crea como ocultos para mí. En cmd, ejecute attrib .gitpara verificar si está oculto. Una vez oculto, un Remove-Item -Recursefunciona sin él -Force.

Mover
fuente
Git para Windows se está creando .gitcomo oculto. En una de mis transcripciones describí cómo cambiarle el nombre gity asegurar que no esté oculto no resuelve el problema en powershell. Agregué esa sección en respuesta a algunos comentarios sobre mi pregunta original.
Christopher Armstrong
@ChristopherArmstrong Funciona para mí después de quitar la configuración oculta ... intente nuevamente con solo Remove-Item -Recurse. Y pruebe la -Forceopción sin desarmar oculto.
Bob
Encontré el problema: no es solo que el .gitdirectorio tenga el Hatributo, sino también que los archivos del paquete .git/objects/packtengan el Ratributo (solo lectura). Una vez que elimine esos atributos también, finalmente puedo eliminar el repositorio git sin pasar -Force.
Christopher Armstrong