tipos tag remove qué existen etiquetas crear git github merge

tag - Git fusionarse con forzar sobrescribir



git tag (3)

No estoy realmente relacionado con esta respuesta, pero abandonaría git pull , que solo ejecuta git fetch seguido de git merge . Estás haciendo tres fusiones, lo que hará que tu Git ejecute tres operaciones de recuperación, cuando una recuperación es todo lo que necesitarás. Por lo tanto:

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 , las opciones -X se pasan a la estrategia de fusión, y tanto la estrategia recursive predeterminada como la estrategia de resolve alternativa toman -X ours o -X theirs (una u otra, pero no ambas). Sin embargo, para comprender lo que hacen, debe saber cómo Git encuentra y trata los conflictos de fusión .

Un conflicto de fusión puede ocurrir dentro de algún archivo 1 cuando la versión base difiere tanto de la versión actual (también llamada local, HEAD o --ours ) como de la otra versión (también llamada remota o --theirs ) de ese mismo archivo. Es decir, la fusión ha identificado tres revisiones (tres confirmaciones): base, la nuestra y la de ellos. La versión "base" es de la base de fusión entre nuestro compromiso y su compromiso, como se encuentra en el gráfico de compromiso (para obtener más información sobre esto, consulte otras publicaciones de StackOverflow). Git ha encontrado dos conjuntos de cambios: "lo que hicimos" y "lo que hicieron". Estos cambios se encuentran (en general) línea por línea, puramente textual . Git no tiene una comprensión real del contenido del archivo; es simplemente comparar cada línea de texto.

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

Si los cambios ocurren en diferentes líneas, por ejemplo, cambiamos de color a colour en la línea 17 y cambian fred a 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 cambios idénticos , Git toma una copia del cambio. Solo si los cambios están en la misma línea, pero son cambios diferentes, o ese caso especial de contexto interferente, obtiene un conflicto de modificación / modificación.

Las opciones -X ours y -X theirs dicen a Git cómo resolver este conflicto, eligiendo solo uno de los dos cambios: el nuestro o el de ellos. Dado que usted dijo que está fusionando la demo (la de ellos) en la master (la nuestra) y desea los cambios de la demo , desearía -X theirs .

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

int i;

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

Si tiene un conjunto de pruebas automatizadas, lo más importante 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 puede hacerlo antes de comprometerse, agregando --no-commit al comando git merge . Dejaremos los detalles de todo esto a otras publicaciones.

1 También puede obtener 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 eliminen todo el archivo (para que tengan un borrar). Git no resolverá estos conflictos por sí solo, independientemente de los argumentos -X .

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 llevar el origin/demo a la demo local (el suyo usa git pull que, si su Git es muy antiguo, no podrá actualizar el origin/demo pero producirá el mismo resultado final). El segundo es traer origin/master al master .

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

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

Digamos que nunca haces tus propios commits en la demo . En este caso podemos deshacernos por completo de la demo del nombre:

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 está haciendo sus propias confirmaciones de la rama de demo , esto no es útil; también podría mantener la fusión existente (pero tal vez agregar --ff-only según el comportamiento que desee), o cambiarlo a un rebase. Tenga en cuenta que los tres métodos pueden fallar: la fusión puede fallar con un conflicto, la fusión con --ff-only puede no ser capaz de avanzar rápidamente, y el rebase puede fallar con un conflicto (el rebase funciona, en esencia, mediante compromisos de selección de cereza , que utiliza la maquinaria de combinación y, por lo tanto, puede generar un conflicto de combinación).

Tengo una rama llamada demo que necesito fusionar con la rama master . Puedo obtener el resultado deseado con los siguientes comandos:

git pull origin demo git checkout master git pull origin master git merge demo git push origin master

Mi única preocupación es, si hay algún problema de fusión , quiero decirle a git que sobrescriba los cambios en la rama master sin darme un aviso de fusión. Entonces, básicamente, los cambios en la rama de demo deberían sobrescribir automáticamente los cambios en la rama master .

Miré a mi alrededor, hay varias opciones, pero no quiero arriesgarme con la fusión.


Puedes probar la opción "nuestra" en git merge,

git merge branch -X nuestro

Esta opción obliga a los trozos en conflicto a que se resuelvan automáticamente limpiamente al favorecer nuestra versión. Los cambios del otro árbol que no entran en conflicto con nuestro lado se reflejan en el resultado de la fusión. Para un archivo binario, todo el contenido se toma de nuestro lado.


Tuve un problema similar, donde necesitaba reemplazar efectivamente cualquier archivo que tuviera cambios / conflictos con una rama diferente.

La solución que encontré fue usar git merge -s ours branch .

Tenga en cuenta que la opción es -s y no -X . -s denota el uso del ours como una estrategia de fusión de nivel superior, -X estaría aplicando la opción ours a la estrategia de fusión recursive , que no es lo que yo (o nosotros) queremos en este caso.

Pasos, donde oldbranch es la rama que desea sobrescribir con newbranch .

  • git checkout newbranch comprueba la rama que desea mantener
  • git merge -s ours oldbranch fusiona en la rama anterior, pero conserva todos nuestros archivos.
  • git checkout oldbranch comprueba la rama que desea sobrescribir
  • get merge newbranch fusiona en la nueva sucursal, sobrescribiendo la antigua sucursal