remota - ¿Es posible que git-merge ignore las diferencias de final de línea?
manejo de git (12)
"git merge-Xrenormalize" funciona como un encanto.
¿Es posible que git merge
ignore las diferencias de final de línea?
Tal vez estoy haciendo la pregunta incorrecta ... pero:
Intenté usar la config.crlf input
pero las cosas se pusieron un poco desordenadas y fuera de control, especialmente cuando lo apliqué después de los hechos .
Por un lado, la aplicación de esta configuración después del hecho no parece afectar los archivos que se comprometieron con el repositorio antes de aplicar esta opción. Otra cosa es que de repente todos los commits ahora resultan en muchos mensajes de advertencia molestos acerca de la conversión de CRLF a LF.
Para ser honesto, realmente no me importa qué línea de finalización se utiliza, personalmente prefiero el estilo de Unix /n
, pero lo que sea. Todo lo que me importa es que git merge
sea un poco más inteligente e ignore las diferencias en los finales de línea.
A veces tengo dos archivos idénticos, pero git los marcaría como en conflicto (y el conflicto es todo el archivo) simplemente porque usan un carácter de terminación de línea diferente.
Actualizar:
Descubrí que git diff
acepta una opción --ignore-space-at-eol
, ¿sería posible dejar que git merge
use también esta opción?
AFAICT, (No lo he probado) puedes usar git diff
para comparar la rama que deseas fusionar con el ancestro común, luego aplicar los resultados con git apply
. Ambos comandos tienen opciones --ignore-whitespace
para ignorar los errores de finalización de línea y espacio en blanco.
Desafortunadamente, si el parche no se aplica limpiamente, toda la operación se cancela. No puedes arreglar conflictos de fusión. Hay una opción --reject
para dejar trozos no compatibles en archivos .rej
, lo que ayuda, pero no es lo mismo que tener los conflictos de fusión que se muestran en un archivo.
Actualización 2013:
Las versiones más recientes de Git autorizan el uso de la fusión con la estrategia recursive
y la opción de estrategia ( -X
):
- de " Git Merge y fijación de espacios mixtos y pestañas con dos ramas ":
git merge -s recursive -Xignore-space-at-eol
Pero usar " -Xignore-space-change
" también es una posibilidad
- Fab-V menciona a below :
git merge master -s recursive -X renormalize
jakub.g also comments that the strategies work also with cherry-picking:
git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize
jakub.g también comments que las estrategias también funcionan con cherry-picking :
#!/bin/sh
# Passing the following parameters to mergetool:
# local base remote merge_result
alocal=$1
base=$2
remote=$3
result=$4
if [ -f $base ]
then
#"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"
# for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
# KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
"C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
#there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
#"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"
# KDiff3 however does know how to merge based on 2 files (not just 3)
"C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi
Esto funciona mucho mejor que ignore-all-space
.
Respuesta original (mayo de 2009)
El parche para ignorar el estilo eol se propuso en junio de 2007 , pero solo se refiere a git diff --ignore-space-at-eol
, no a git merge
.
En ese momento, la pregunta ha sido solicitada:
¿Debería
--ignore-space-at-eol
ser una opción paragit-merge
?
Las fusiones son donde esta funcionalidad importa.
¿Cuál es la semántica de una fusión resuelta automáticamente con esas opciones en efecto? ¿Se usan solo para la detección de cambio de nombre, o nosotros, por ejemplo, no estamos en conflicto con solo los cambios en el espacio en blanco? Y si no lo hacemos, ¿qué versión aceptamos automáticamente?
Julio C Hamano no era exactamente entusiasta:
Esto ciertamente es tentador, pero sospecho que debería dejarse en rondas posteriores.
Sospecho que introduciría un concepto de dos tipos diferentes de diffs, uno para ser procesado mecánicamente (es decir, usar para fusionar con "git-merge-recursive", y aplicarlo con "git-am"), y otro para ser inspeccionado por humanos a entender.
A menudo puede ser útil administrar la entrada para el último caso, aunque la salida de la comparación de los archivos de entrada contaminados puede no ser fácilmente utilizable para la aplicación mecánica.
La idea general, cuando se trata de git merge
, es confiar en la herramienta de fusión de terceros.
Por ejemplo, he configurado DiffMerge para que sea la herramienta de fusión de Git, estableciendo un conjunto de reglas que permite que esa herramienta de fusión ignore eol para cierto tipo de archivos.
Configuración en Windows, con MSysGit1.6.3, ya sea para DOS o sesión de Git bash, con DiffMerge o KDiff3:
- establece un directorio en tu PATH (aquí:
c:/HOMEWARE/cmd
). - agregue en ese directorio el script merge.sh (wrapper para su herramienta de fusión favorita)
merge.sh:
git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh /"$PWD/$LOCAL/" /"$PWD/$BASE/" /"$PWD/$REMOTE/" /"$PWD/$MERGED/"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false
- Declare su envoltorio de fusión para Git
Comandos de configuración de Git:
git config ---system core.autoCRLF=false
- Verifique que autoCRLF sea falso
git config a nivel de sistema:
git config merge.renormalize true
- Pruebe que, cuando dos líneas son idénticas (pero sus caracteres eol), tanto DiffMerge como KDiff3 ignorarán esas líneas durante una combinación.
Script DOS (nota: el comando dos2unix viene de aquí y se usa para simular un estilo eol de Unix. Ese comando se ha copiado en el directorio mencionado al principio de esta respuesta):
C:/HOMEWARE/git/test>mkdir test_merge C:/HOMEWARE/git/test>cd test_merge C:/HOMEWARE/git/test/test_merge>git init C:/HOMEWARE/git/test/test_merge>echo a1 > a.txt & echo a2 >> a.txt C:/HOMEWARE/git/test/test_merge>git add a.txt C:/HOMEWARE/git/test/test_merge>git commit -m "a.txt, windows eol style" C:/HOMEWARE/git/test/test_merge>git checkout -b windows Switched to a new branch ''windows'' C:/HOMEWARE/git/test/test_merge>echo a3 >> a.txt & echo a4 >> a.txt C:/HOMEWARE/git/test/test_merge>git add a.txt C:/HOMEWARE/git/test/test_merge>git commit -m "add two lines, windows eol style" C:/HOMEWARE/git/test/test_merge>git checkout master C:/HOMEWARE/git/test/test_merge>git checkout -b unix Switched to a new branch ''unix'' C:/HOMEWARE/git/test/test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt C:/HOMEWARE/git/test/test_merge>dos2unix a.txt Dos2Unix: Processing file a.txt ... C:/HOMEWARE/git/test/test_merge>git add a.txt C:/HOMEWARE/git/test/test_merge>git commit -m "add 3 lines, all file unix eol style" [unix c433a63] add 3 lines, all file unix eol style C:/HOMEWARE/git/test/test_merge>git merge windows Auto-merging a.txt CONFLICT (content): Merge conflict in a.txt Automatic merge failed; fix conflicts and then commit the result. C:/HOMEWARE/git/test/test_merge>git ls-files -u 100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt 100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt 100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txt C:/HOMEWARE/git/test/test_merge>git mergetool Merging the files: a.txt Normal merge conflict for ''a.txt'': {local}: modified {remote}: modified Hit return to start merge resolution tool (diffmerge):
En este punto (Hitting "return"), se abrirá DiffMerge o KDiff3, y verá por sí mismo qué líneas se fusionan realmente y qué líneas se ignoran.
Advertencia : el archivo de resultados siempre estará en el modo eol de Windows (CRLF) con DiffMerge ...
KDiff3 ofrece guardar de una forma u otra.
Ahora me parece que la mejor manera es normalizar las terminaciones de línea en ambas ramas (y confirmar) antes de fusionarlas.
Busqué en Google "convertir crlf a lf" y encontré esto como los primeros resultados:
http://stahlforce.com/dev/index.php?tool=remcrlf
Lo descargué y usé, parece una buena herramienta.
>sfk remcr . .py
Asegúrate de especificar un directorio y un tipo de archivo (por ejemplo, .py); de lo contrario, ¡podría tratar de meterse con el contenido del directorio .git
!
Como en esta respuesta: https://.com/a/5262473/943928
Puede probar: git merge -s recursive -Xignore-space-at-eol
Después de leer Resolver conflictos de combinación: Forzar sobrescribir todos los archivos
Finalmente resolví mi versión de este problema. Estaba tratando de obtener actualizaciones del repositorio de subida pero mi actual estaba teniendo problemas relacionados con CRLF y no pude fusionarme como resultado. Debe tenerse en cuenta que no tuve NINGÚN CAMBIO LOCAL que deba preocuparme. Los siguientes pasos resolvieron mi problema:
Según las instrucciones de github sobre la sincronización de horquillas ( https://help.github.com/articles/syncing-a-fork/ ):
git fetch upstream
git reset --hard upstream/master
Mi comprensión limitada de git me dice que esto está haciendo lo que quiero: cambiar mi bifurcación (sin cambios reales no confirmados) para obtener todos los cambios realizados en la fuente de subida. De acuerdo con la página de origen, este paso normalmente no debería ser requerido, pero el problema CRLF lo requería.git merge upstream/master
-
git push
Después de leer https://.com/a/12194759/1441706 y https://.com/a/14195253/1441706
para mí, este comando hizo el truco a la perfección:
>sfk remcr . .py
Estaba buscando la misma respuesta y descubrí this
Fusionar sucursales con diferentes atributos de checkin / checkout
Si ha agregado atributos a un archivo que causa el cambio del formato del repositorio canónico para ese archivo, como agregar un filtro limpio / borroso o atributos de texto / eol / ident, fusionar cualquier cosa donde el atributo no esté en su lugar normalmente provocaría conflictos de fusión .
Para evitar estos conflictos de fusión innecesarios, puede pedírsele a git que ejecute un check-in virtual y el check-in de las tres etapas de un archivo al resolver una fusión de tres vías configurando la variable de configuración merge.renormalize. Esto evita que los cambios causados por la conversión de check-in provoquen conflictos de fusión falsos cuando un archivo convertido se fusiona con un archivo no convertido.
Siempre que una "mancha → limpiar" tenga como resultado el mismo resultado que una "limpieza" incluso en archivos que ya están manchados, esta estrategia resolverá automáticamente todos los conflictos relacionados con el filtro. Los filtros que no actúan de esta manera pueden causar conflictos de combinación adicionales que deben resolverse manualmente.
Entonces, ejecutar este comando en cualquier repositorio hará el truco:
git merge master -s recursive -X renormalize
Lo que hice fue dejar todo como predeterminado (es decir, autocrlf = verdadero), tocar todos los archivos (buscar .exec touch {} /;), dejar que git los vea como ''modificados'' y volver a enviarlos, y terminar con ellos. De lo contrario, siempre estarás plagado de mensajes molestos o diferencias sorprendentes, o tendrás que desactivar todas las funciones de espacio en blanco de git.
Perderá la información de culpa, pero es mejor hacerlo más temprano que tarde :)
No parece que esto se pueda hacer directamente, pero esta publicación sugiere una alternativa.
sin embargo, sugiero usar herramienta como sed para lograr terminaciones de línea correctas, y luego archivos diff. Pasé un par de horas en proyectos diferentes con varios finales de línea.
La mejor manera fue:
- copie solo los archivos del proyecto (omita
.git
directorio.git
) a otro directorio, cree un repositorio en él, luego agregue los archivos y complételos (debe estar en la rama maestra en el nuevo repositorio). - copiar archivos del segundo proyecto a la misma carpeta, pero otra rama, por ejemplo,
dev
(git checkout -b dev
), confirmar los archivos en esta rama y ejecutar (si el primer proyecto está en el maestro):git diff master..dev --names-only
para ver solo los nombres de los archivos modificados
http://stahlforce.com/dev/index.php?tool=remcrlf
Lo intenté, pero si después de la última línea de tu código ya no tenías CRLF, agrega una LF y el archivo se ve modificado en git. Aparte de eso, funciona.