Tengo una rama llamada demo
que necesito fusionar con la master
rama. 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 que, si hay algún problema de fusión , quiero indicarle git
que sobrescriba los cambios en la master
rama sin darme un mensaje de fusión. Entonces, básicamente, los cambios en la demo
rama deberían sobrescribir automáticamente los cambios en la master
rama.
Miré a mi alrededor, hay varias opciones, pero no quiero correr riesgos con la fusión.
git push -f origin master
-f
opción con elmerge
comando y no con elpush
comando?Respuestas:
No está realmente relacionado con esta respuesta, pero me desharía
git pull
, que solo se ejecutagit fetch
seguido degit 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 necesitas. Por lo tanto:Controlando la fusión más complicada
La parte más interesante aquí es
git merge -X theirs
. Como señaló root545 , las-X
opciones se pasan a la estrategia de fusión, y tanto larecursive
estrategia predeterminada como laresolve
estrategia 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, nuestra y 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). Luego, Git encontró dos conjuntos de cambios: "lo que hicimos" y "lo que hicieron". Estos cambios se encuentran (en general) en una línea por línea, puramente textualbase. 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 ve en la
git diff
salida y, como siempre, también tienen contexto . 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 diferentes líneas, por ejemplo, cambiamos
color
a lacolour
línea 17 y ellosfred
a labarney
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 de interferencia, se obtiene un conflicto de modificación / modificación.Las opciones
-X ours
y le-X theirs
dicen a Git cómo resolver este conflicto, eligiendo solo uno de los dos cambios: el nuestro o el de ellos. Como dijiste que estás fusionandodemo
(el de ellos) conmaster
(el nuestro) y quieres los cambios dedemo
, querrás-X theirs
.Aplicar a ciegas
-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 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:En nuestra versión, eliminamos la variable no utilizada para que desaparezca la advertencia del compilador, y en su versión, agregan un bucle algunas líneas más tarde, utilizando
i
como contador de bucle. Si combinamos los dos cambios, el código resultante ya no se compila. La-X
opción no es de ayuda aquí ya que los cambios están en diferentes líneas .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 puede hacerlo antes de confirmar, agregando
--no-commit
algit merge
comando. Dejaremos los detalles de todo esto para otras publicaciones.1 Tambié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 eliminen todo el archivo (para que tengan un Eliminar). Git no resolverá estos conflictos por sí solo, independientemente de los
-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 traerlo
origin/demo
al localdemo
(los usos suyosgit pull
que, si su Git es muy antiguo, no se actualizaránorigin/demo
pero producirán el mismo resultado final). La segunda es llevarorigin/master
amaster
.No tengo claro quién está actualizando
demo
y / omaster
. Si escribe su propio código en su propiademo
rama, y otros escriben código y lo empujan a lademo
ramaorigin
, 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 utilizargit rebase
en su lugar. Por otro lado, si nunca realiza ninguna de sus propias confirmacionesdemo
, ni siquiera necesita unademo
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 usargit merge --ff-only origin/demo
: esto avanzará rápidamentedemo
para que coincida con el actualizadoorigin/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
, a pesar de que está haciendo la combinación demaster
, por lo que definitivamente necesita unamaster
. 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 también debería ser asígit merge --ff-only origin/master
.Digamos que nunca haces tus propios compromisos
demo
. En este caso, podemos deshacernos del nombre pordemo
completo:Si está haciendo sus propias
demo
confirmaciones de rama, esto no es útil; también puede mantener la combinación existente (pero tal vez agregarla--ff-only
según el comportamiento que desee), o cambiarla para hacer una 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
puede no poder avanzar rápidamente y la rebase puede fallar con un conflicto (la rebase funciona, en esencia, mediante la selección de confirmaciones, que usa la combinación maquinaria y, por lo tanto, puede tener un conflicto de fusión).fuente
Tuve un problema similar, en el que 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 deours
como una estrategia de fusión de nivel superior,-X
sería aplicar laours
opción a larecursive
estrategia de fusión, que no es lo que yo (o queremos) queremos en este caso.Pasos, dónde
oldbranch
está la rama con la que desea sobrescribirnewbranch
.git checkout newbranch
comprueba la sucursal que quieres conservargit merge -s ours oldbranch
se fusiona en la rama anterior, pero conserva todos nuestros archivos.git checkout oldbranch
comprueba la rama que quieres sobrescribirget merge newbranch
se fusiona en la nueva rama, sobrescribiendo la antiguafuente
Este enfoque de fusión agregará una confirmación sobre la
master
cual se pega en lo que seafeature
, sin quejarse de conflictos u otras tonterías.Antes de tocar nada
Ahora prepara maestro
Consigue
feature
todos los vestidosIr a matar
fuente
Changes from the other tree that do not conflict with our side are reflected in the merge result
. No funcionó para mí, ya que había fusionado limpiamente confirmaciones en mi rama que se estaba sobrescribiendo. ¿Hay alguna otra manera?Puedes probar la opción "nuestra" en git merge,
fuente
demo
versión sea preferida a pesar de que se está fusionandomaster
. También lo hay-X theirs
, pero no está claro si esto es lo que realmente quiere el OP.ours
hace cuando se usa en el backend con la-s
opción. Cuando se usaours
con-X
: Descarta todo lo que hizo el otro árbol, declarando que nuestro historial contiene todo lo que sucedió en él. fuenteCuando intenté usar
-X theirs
y otros interruptores de comando relacionados, seguí obteniendo un compromiso de fusión. Probablemente no lo entendía correctamente. Una alternativa fácil de entender es simplemente eliminar la rama y luego rastrearla nuevamente.Esto no es exactamente una "fusión", pero esto es lo que estaba buscando cuando me encontré con esta pregunta. En mi caso, quería extraer cambios de una rama remota que fueron presionados a la fuerza.
fuente