in

github: fusión de Git con sobrescritura forzada

apple touch icon@2

No está realmente relacionado con esta respuesta, pero me desharía git pull, que simplemente corre git fetch seguido por git merge. Está haciendo tres fusiones, lo que hará que su Git ejecute tres operaciones de recuperación, cuando una recuperación es todo lo que necesita. Por eso:

git fetch origin   # update all our origin/* remote-tracking branches

git checkout demo         # if needed -- your example assumes you're on it
git merge origin/demo     # if needed -- see below

git checkout master
git merge origin/master

git merge -X theirs demo   # but see below

git push origin master     # again, see below

Controlando la fusión más complicada

La parte más interesante aquí es git merge -X theirs. Como señaló root545, el -X las opciones se pasan a la estrategia de fusión, y tanto las opciones predeterminadas recursive estrategia y la alternativa resolve estrategia toma -X ours o -X theirs (uno u otro, pero no ambos). Sin embargo, para comprender lo que hacen, debe saber cómo encuentra y trata Git, fusionar conflictos.

Puede producirse un conflicto de fusión dentro de algún archivo1 cuando el base la versión difiere tanto de la Actual (también llamado local, HEAD o --ours) versión y el otro (también llamado remoto o --theirs) versión de ese mismo archivo. Es decir, la fusión ha identificado tres revisiones (tres confirmaciones): base, nuestra y de ellos. La versión «base» es de fusionar base entre nuestra confirmación y su confirmación, como se encuentra en el gráfico de confirmación (para obtener más información sobre esto, consulte otras publicaciones de StackOverflow). Luego, Git encontró dos conjuntos de cambios: «lo que hicimos» y «lo que hicieron». Estos cambios se encuentran (en general) línea por línea, puramente textual base. Git no tiene una comprensión real del contenido de los archivos; es simplemente comparar cada línea de texto.

Estos cambios son lo que ves en git diff salida, y como siempre, tienen contexto así como. Es posible que las cosas que cambiamos estén en líneas diferentes de las que cambiaron, por lo que los cambios parecen no colisionar, pero el contexto también ha cambiado (por ejemplo, debido a que nuestro cambio está cerca de la parte superior o inferior del archivo, por lo que el archivo se agota en nuestra versión, pero en la de ellos también han agregado más texto en la parte superior o inferior).

Si los cambios ocurren en diferente líneas, por ejemplo, cambiamos color para colour en la línea 17 y cambian fred para barney en la línea 71, entonces no hay conflicto: Git simplemente toma ambos cambios. Si los cambios ocurren en las mismas líneas, pero son idéntico cambios, Git toma una copia del cambio. Solo si los cambios están en las mismas líneas, pero son cambios diferentes, o ese caso especial de contexto de interferencia, se obtiene un conflicto de modificación / modificación.

los -X ours y -X theirs Las opciones le dicen a Git cómo resolver este conflicto, eligiendo solo uno de los dos cambios: el nuestro o el de ellos. Desde que dijiste que te estas fusionando demo (de ellos) en master (nuestro) y queremos los cambios de demo, querrías -X theirs.

Aplicar a ciegas -X, sin embargo, es peligroso. ¡El hecho de que nuestros cambios no hayan entrado en conflicto línea por línea no significa que nuestros cambios en realidad no entren en conflicto! Un ejemplo clásico ocurre en lenguajes con declaraciones de variables. La versión base puede declarar una variable no utilizada:

int i;

En nuestra versión, eliminamos la variable no utilizada para que desaparezca una advertencia del compilador, y en su versión, agregan un bucle algunas líneas más tarde, usando i como el contador de bucle. Si combinamos los dos cambios, el código resultante ya no se compila. los -X La opción no es de ayuda aquí ya que los cambios están en diferentes lineas.

Si tiene un conjunto de pruebas automatizado, lo más importante que debe hacer es ejecutar las pruebas después de la fusión. Puede hacer esto después de comprometerse y arreglar las cosas más tarde si es necesario; o puedes hacerlo antes de comprometiéndose, agregando --no-commit al git merge mando. Dejaremos los detalles de todo esto para otras publicaciones.


1También puede tener conflictos con respecto a las operaciones de «todo el archivo», por ejemplo, tal vez arreglemos la ortografía de una palabra en un archivo (para que tengamos un cambio), y Eliminar el archivo completo (para que se eliminen). Git no resolverá estos conflictos por sí solo, independientemente de -X argumentos.


Hacer menos fusiones y / o fusiones más inteligentes y / o usar rebase

Hay tres fusiones en nuestras dos secuencias de comandos. El primero es traer origin/demo en el local demo (el tuyo usa git pull que, si su Git es muy antiguo, no se actualizará origin/demo pero producirá el mismo resultado final). El segundo es traer origin/master dentro master.

No tengo claro quién está actualizando demo y / o master. Si escribe su propio código por su cuenta demo rama, y otros escriben código y lo empujan a la demo rama en origin, entonces esta fusión del primer paso puede tener conflictos o producir una fusión real. La mayoría de las veces, es mejor usar rebase, en lugar de fusionar, para combinar el trabajo (es cierto que esto es una cuestión de gustos y opiniones). Si es así, es posible que desee utilizar git rebase en lugar de. Por otro lado, si nunca realiza ninguna de sus propias confirmaciones en demotu ni siquiera necesitar a demo rama. Alternativamente, si desea automatizar mucho de esto, pero puede verificar cuidadosamente cuando hay confirmaciones que tanto usted como otros hicieron, es posible que desee usar git merge --ff-only origin/demo: esto adelantará su demo para que coincida con el actualizado origin/demo si es posible, y simplemente fallará por completo si no (en ese momento puede inspeccionar los dos conjuntos de cambios y elegir una combinación real o una rebase según corresponda).

Esta misma lógica se aplica a master, aunque estás haciendo la fusión sobre master, así que definitivamente necesitas un master. Sin embargo, es incluso más probable que desee que la fusión falle si no se puede realizar como una no fusión de avance rápido, por lo que probablemente esto también debería ser git merge --ff-only origin/master.

Digamos que nunca haces tus propios compromisos en demo. En este caso podemos deshacernos del nombre demo enteramente:

git fetch origin   # update origin/*

git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"

git merge -X theirs origin/demo || die "complex merge conflict"

git push origin master

Si tu están haciendo lo tuyo demo la rama se confirma, esto no es útil; también podría mantener la combinación existente (pero tal vez agregar --ff-only dependiendo del comportamiento que desee), o cámbielo para hacer un rebase. Tenga en cuenta que los tres métodos pueden fallar: la combinación puede fallar con un conflicto, la combinación con --ff-only es posible que no pueda avanzar rápidamente y la rebase puede fallar con un conflicto (la rebase funciona, en esencia, cosecha de la cereza commits, que usa la maquinaria de fusión y, por lo tanto, puede generar un conflicto de fusión).

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

DBMS distribuido – Bases de datos distribuidas

iZikTSRa7VUU6FMKTkHfDf 1200 80

Cómo encontrar a Isabelle en Animal Crossing: New Horizons