tag - ¿Cuál es la mejor estrategia de manejo de CRLF(retorno de carro, avance de línea) con Git?
git tag best practices (9)
Intenté enviar archivos con líneas CRLF-final, pero falló.
Pasé todo un día de trabajo en mi computadora con Windows probando diferentes estrategias y casi me detuve para dejar de usar Git y, en cambio, probar Mercurial .
Por favor comparta solo una buena práctica por respuesta.
Casi cuatro años después de hacer esta pregunta, ¡finalmente encontré una respuesta que me satisface completamente !
Vea los detalles en github: guía de ayuda para tratar con los finales de línea .
Git le permite establecer las propiedades de fin de línea para un repositorio directamente usando el atributo de texto en el archivo
.gitattributes
. Este archivo se confirma en el repositorio y anula la configuracióncore.autocrlf
, lo que le permite garantizar un comportamiento coherente para todos los usuarios, independientemente de su configuración de git.
Y por lo tanto
La ventaja de esto es que su configuración de final de línea ahora viaja con su repositorio y no tiene que preocuparse de si los colaboradores tienen la configuración global adecuada.
Aquí hay un ejemplo de un archivo .gitattributes
# Auto detect text files and perform LF normalization
* text=auto
*.cs text diff=csharp
*.java text diff=java
*.html text diff=html
*.css text
*.js text
*.sql text
*.csproj text merge=union
*.sln text merge=union eol=crlf
*.docx diff=astextplain
*.DOCX diff=astextplain
# absolute paths are ok, as are globs
/**/postinst* text eol=lf
# paths that don''t start with / are treated relative to the .gitattributes folder
relative/path/*.txt text eol=lf
Hay una colección conveniente de archivos .gitattributes listos para usar para los lenguajes de programación más populares. Es útil para comenzar.
Una vez que haya creado o ajustado sus .gitattributes
, debe realizar una re-normalización de los finales de línea de una vez por todas.
Tenga en cuenta que la aplicación GitHub Desktop puede sugerir y crear un archivo .gitattributes
después de abrir el repositorio Git de su proyecto en la aplicación. Para intentarlo, haga clic en el icono de engranaje (en la esquina superior derecha)> Configuración del repositorio ...> Finales de línea y atributos. Se le pedirá que agregue los .gitattributes
recomendados y, si está de acuerdo, la aplicación también realizará una normalización de todos los archivos en su repositorio.
Finalmente, el artículo Mind the End of Your Line proporciona más antecedentes y explica cómo Git ha evolucionado en los asuntos que nos ocupan. Considero que esto requiere lectura .
Probablemente tenga usuarios en su equipo que usen EGit o JGit (herramientas como Eclipse y TeamCity los usan) para confirmar sus cambios. Entonces no tienes suerte, como @gatinueta explicó en los comentarios de esta respuesta:
Esta configuración no lo satisfará completamente si tiene personas que trabajan con Egit o JGit en su equipo, ya que esas herramientas simplemente ignorarán .gitattributes y alegremente revisarán los archivos CRLF https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372
Un truco podría ser hacer que confirmen sus cambios en otro cliente, por ejemplo, SourceTree . En aquel entonces, nuestro equipo prefería esa herramienta a EGit de Eclipse para muchos casos de uso.
¿Quién dijo que el software es fácil? : - /
Dos estrategias alternativas para ser coherentes con los finales de línea en entornos mixtos (Microsoft + Linux + Mac):
A. Configuración global por todos los repositorios
1) Convertir todo a un formato
find . -type f -not -path "./.git/*" -exec dos2unix {} /;
git commit -a -m ''dos2unix conversion''
2) Establezca core.autocrlf
para input
en Linux / UNIX o true
en MS Windowns (repositorio o global)
git config --global core.autocrlf input
3) [Opcional] establezca core.safecrlf
en true
(para detener) o warn
(para cantar :) para agregar protección adicional si la transformación de nueva línea invertida resultaría en el mismo archivo
git config --global core.safecrlf true
B. O por configuración del repositorio
1) Convertir todo a un formato
find . -type f -not -path "./.git/*" -exec dos2unix {} /;
git commit -a -m ''dos2unix conversion''
2) agregue el archivo .gitattributes
a su repositorio
echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m ''adding .gitattributes for unified line-ending''
No te preocupes por tus archivos binarios: Git debería ser lo suficientemente inteligente como para hacerlo.
El uso de core.autocrlf=false
todos los archivos se core.autocrlf=false
como actualizados tan pronto como los verifiqué en mi proyecto de Visual Studio 2010 . Los otros dos miembros del equipo de desarrollo también están usando sistemas Windows, por lo que no entró en juego un entorno mixto, pero la configuración predeterminada que viene con el repositorio siempre marcó todos los archivos como actualizados inmediatamente después de la clonación.
Supongo que la conclusión es encontrar qué configuración de CRLF funciona para su entorno. Especialmente porque en muchos otros repositorios en nuestros cuadros de Linux, la configuración de autocrlf = true
produce mejores resultados.
Más de 20 años después, todavía estamos lidiando con las diferencias de final de línea entre sistemas operativos ... triste.
Esta es solo una solución alternativa :
En casos normales, use las soluciones que se envían con git. Estos funcionan muy bien en la mayoría de los casos. Forzar a LF si comparte el desarrollo en sistemas basados en Windows y Unix configurando .gitattributes .
En mi caso hubo más de 10 programadores desarrollando un proyecto en Windows. Este proyecto se registró con CRLF y no había ninguna opción para forzar a LF.
Algunas configuraciones fueron escritas internamente en mi máquina sin ninguna influencia en el formato LF; por lo tanto, algunos archivos se cambiaron globalmente a LF en cada cambio de archivo pequeño.
Mi solución:
Windows-Machines: deja todo como está. No te preocupes por nada, ya que eres un desarrollador predeterminado de Windows ''Lone Wolf'' y tienes que manejarlo así: "No hay otro sistema en el mundo, ¿verdad?"
Unix-Machines
Agregue las siguientes líneas a la sección
[alias]
una configuración. Este comando enumera todos los archivos modificados (es decir, modificados / nuevos):lc = "!f() { git status --porcelain / | egrep -r /"^(/?| )./*//(.[a-zA-Z])*/" / | cut -c 4- ; }; f "
Convierte todos esos archivos modificados en formato DOS:
unix2dos $(git lc)
Opcionalmente ...
Crea un hook git para esta acción para automatizar este proceso.
Use params e inclúyalo y modifique la función
grep
para que coincida solo con nombres de archivos particulares, por ejemplo:... | egrep -r "^(/?| ).*/.(txt|conf)" | ...
Siéntase libre de hacerlo aún más conveniente usando un atajo adicional:
c2dos = "!f() { unix2dos $(git lc) ; }; f "
... y dispara las cosas convertidas escribiendo
git c2dos
Estas son las dos opciones para usuarios de Windows y Visual Studio que comparten código con usuarios de Mac o Linux . Para una explicación extendida, lea el manual de atributos de gitat .
* texto = auto
En el archivo .gitattributes
tu repositorio agrega:
* text=auto
Esto normalizará todos los archivos con finales de línea LF
en el repositorio.
Y dependiendo de su sistema operativo (configuración core.eol
), los archivos en el árbol de trabajo se normalizarán a LF
para sistemas basados en Unix o CRLF
para sistemas Windows.
Esta es la configuración que utilizan los repositorios de Microsoft .NET .
Ejemplo:
Hello/r/nWorld
Se normalizará en el repo siempre como:
Hello/nWorld
Al finalizar la compra, el árbol de trabajo en Windows se convertirá a:
Hello/r/nWorld
Al finalizar la compra, el árbol de trabajo en Mac se dejará como:
Hello/nWorld
Nota: si su repo ya contiene archivos no normalizados,
git status
mostrará estos archivos como completamente modificados la próxima vez que realice algún cambio en ellos, y podría ser un dolor para otros usuarios fusionar sus cambios más adelante. Consulte la actualización de un repositorio después de cambiar los finales de línea para obtener más información.
core.autocrlf = true
Si el text
no se especifica en el archivo .gitattributes
, Git usa la variable de configuración core.autocrlf
para determinar si el archivo debe convertirse.
Para los usuarios de Windows, git config --global core.autocrlf true
es una excelente opción porque:
- Los archivos se normalizan a los finales de línea
LF
solo cuando se agregan al repositorio. Si hay archivos que no están normalizados en el repositorio, esta configuración no los tocará. - Todos los archivos de texto se convierten a finales de línea
CRLF
en el directorio de trabajo.
El problema con este enfoque es que:
- Si es un usuario de Windows con
autocrlf = input
, verá un montón de archivos con finales de líneaLF
. No es un peligro para el resto del equipo, ya que sus compromisos aún se normalizarán con los finales de líneaLF
. - Si es un usuario de Windows con
core.autocrlf = false
, verá un montón de archivos con finales de líneaLF
y puede introducir archivos con finales de líneaCRLF
en el repositorio. - La mayoría de los usuarios de Mac utilizan
autocrlf = input
y pueden obtener archivos con terminaciones de archivosCRLF
, probablemente de usuarios de Windows concore.autocrlf = false
.
He pasado horas para encontrar el mejor uso posible de .gitattributes
, para finalmente darme cuenta de que no puedo contar con ello.
Desafortunadamente, mientras existan editores basados en JGit (que no puedan manejar .gitattributes
correctamente), la solución segura es forzar a LF en todas partes, incluso en el nivel de editor.
Use los siguientes desinfectantes anti-CRLF
.
Windows / clientes de Linux:
core.autocrlf=input
.gitattributes
comprometidos:* text=auto eol=lf
cometido
.editorconfig
( http://editorconfig.org/ ) que es una especie de formato estandarizado, combinado con complementos de editor:
--- Actualización ---
Incluso si no desea utilizar la estrategia anterior, el siguiente comando es su amigo ( Nota: en los clientes de Windows solo funciona a través de git-bash
y en los clientes de Linux solo si se compila con --with-libpcre
en ./configure
).
# Print all files that have been committed with CRLF (more correctly that contain CR), so that you normalize them.
git grep -I --files-with-matches --perl-regexp ''/r'' HEAD
Un ejemplo doloroso :
Netbeans 8.2 (en Windows), confirmará incorrectamente todos los archivos de texto con CRLF en el repositorio , a menos que haya establecido explícitamente core.autocrlf
como global . Esto contradice el comportamiento estándar de git client y causa muchos problemas más adelante, al actualizar / fusionar. Esto es lo que hace que algunos archivos parezcan diferentes (aunque no lo sean) incluso cuando se revierte .
El mismo comportamiento en netbeans ocurre incluso si ha agregado .gitattributes
correctos a su proyecto.
Al usar el comando anterior después de una confirmación, al menos le ayudará a detectar antes si su git repo tiene problemas de final de línea.
Intente establecer la opción de configuración core.autocrlf
en true
. También eche un vistazo a la opción core.safecrlf
.
En realidad, parece que core.safecrlf
ya podría estar configurado en su repositorio, porque (el énfasis es mío):
Si este no es el caso de la configuración actual de core.autocrlf, git rechazará el archivo .
Si este es el caso, entonces es posible que desee verificar que su editor de texto esté configurado para usar los finales de línea de manera consistente. Es probable que tenga problemas si un archivo de texto contiene una combinación de finales de línea LF y CRLF.
Finalmente, creo que la recomendación de simplemente "usar lo que se te da" y usar líneas terminadas en LF en Windows causará más problemas de los que resuelve. Git tiene las opciones anteriores para tratar de manejar los finales de línea de una manera sensata, por lo que tiene sentido usarlos.
No convierta los finales de línea. El trabajo de VCS no es interpretar los datos, solo almacenarlos y versionarlos. Cada editor de texto moderno puede leer ambos tipos de finales de línea de todos modos.
Casi siempre quieres autocrlf=input
menos que realmente sepas lo que estás haciendo.
Un poco de contexto adicional a continuación:
Debe ser
core.autocrlf=true
si te gusta el final de DOS ocore.autocrlf=input
si prefieres las líneas nuevas de Unix. En ambos casos, su repositorio Git tendrá solo LF, que es lo correcto. El único argumento paracore.autocrlf=false
fue que la heurística automática puede detectar incorrectamente algunos binarios como texto y luego su mosaico se corromperá. Entonces, secore.safecrlf
opcióncore.safecrlf
para advertir a un usuario si ocurre un cambio irreversible. De hecho, hay dos posibilidades de cambios irreversibles: el final de línea mixto en el archivo de texto, en esta normalización es deseable, por lo que esta advertencia puede ignorarse o (muy poco probable) que Git detecte incorrectamente su archivo binario como texto. Entonces necesitas usar atributos para decirle a Git que este archivo es binario.
El párrafo anterior fue originalmente sacado de un hilo en gmane.org, pero desde entonces ha caído.