Causa posible # 1 - Normalización de final de línea
Una situación en la que esto puede suceder es cuando el archivo en cuestión se registró en el repositorio sin la configuración correcta para las terminaciones de línea (1), lo que resultó en un archivo en el repositorio con terminaciones de línea incorrectas o terminaciones de línea mixtas. Para confirmar, verifique que git diff
solo muestre cambios en los finales de línea (estos pueden no ser visibles por defecto, intente git diff | cat -v
ver los retornos de carro como ^M
caracteres literales ).
Posteriormente, alguien probablemente agregó .gitattributes
o modificó la core.autocrlf
configuración para normalizar las terminaciones de línea (2). Basado en la .gitattributes
configuración global o, Git ha aplicado cambios locales a su copia de trabajo que aplican la línea que finaliza la normalización solicitada. Desafortunadamente, por alguna razón git reset --hard
no deshace estos cambios de normalización de línea.
Solución
Las soluciones en las que se restablecen las terminaciones de línea locales no resolverán el problema. Cada vez que git "ve" el archivo, intentará volver a aplicar la normalización, dando como resultado el mismo problema.
La mejor opción es dejar que git aplique la normalización que desea mediante la normalización de todas las terminaciones de línea en el repositorio para que coincida con .gitattributes
, y confirmar esos cambios; consulte Intentar arreglar las terminaciones de línea con git filter-branch, pero no tener suerte .
Si realmente desea intentar y revertir los cambios en el archivo manualmente, entonces la solución más fácil parece ser borrar los archivos modificados, y luego decirle a git que los restaure, aunque noto que esta solución no parece funcionar consistentemente al 100% el tiempo ( ADVERTENCIA: ¡NO ejecute esto si sus archivos modificados tienen cambios que no sean terminaciones de línea!):
git status --porcelain | grep "^ M" | cut -c4- | xargs rm
git checkout -- .
Tenga en cuenta que, a menos que normalice las terminaciones de línea en el repositorio en algún momento, seguirá encontrándose con este problema.
Causa posible # 2 - Insensibilidad de mayúsculas y minúsculas
La segunda causa posible es la insensibilidad a mayúsculas y minúsculas en Windows o Mac OS / X. Por ejemplo, supongamos que existe una ruta como la siguiente en el repositorio:
/foo/bar
Ahora alguien en Linux compromete archivos /foo/Bar
(probablemente debido a una herramienta de compilación o algo que creó ese directorio) y empuja. En Linux, esto es en realidad ahora dos directorios separados:
/foo/bar/fileA
/foo/Bar/fileA
Verificar este repositorio en Windows o Mac puede resultar en modificaciones fileA
que no se pueden restablecer, porque en cada restablecimiento, git en Windows se desprotege /foo/bar/fileA
, y luego porque Windows no distingue entre mayúsculas y minúsculas, sobrescribe el contenido de fileA
con /foo/Bar/fileA
, lo que hace que se "modifiquen".
Otro caso puede ser un archivo (s) individual que existe en el repositorio, que cuando se desprotege en un sistema de archivos que no distingue entre mayúsculas y minúsculas, se superpondría. Por ejemplo:
/foo/bar/fileA
/foo/bar/filea
Puede haber otras situaciones similares que podrían causar tales problemas.
git en sistemas de archivos que no distinguen entre mayúsculas y minúsculas realmente debería detectar esta situación y mostrar un mensaje de advertencia útil, pero actualmente no lo hace (esto puede cambiar en el futuro - vea esta discusión y los parches propuestos relacionados en la lista de correo de git.git).
Solución
La solución es alinear el caso de los archivos en el índice git y el caso en el sistema de archivos de Windows. Esto se puede hacer en Linux que mostrará el verdadero estado de las cosas, O en Windows con la muy útil utilidad de código abierto Git-Unite . Git-Unite aplicará los cambios de caso necesarios al índice git, que luego se puede confirmar en el repositorio.
(1) Probablemente fue alguien que usó Windows, sin ninguna .gitattributes
definición para el archivo en cuestión, y que utilizó la configuración global predeterminada para la core.autocrlf
cual es false
(ver (2)).
(2) http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
.
significa directorio actual, no directorio raíz