Estoy en la sucursal foo
y deseo fusionarme para develop
mi twig de function foo
. Quiero que todos los conflictos se resuelvan automáticamente y que el código de la sucursal sea automáticamente escrito. Desde la sucursal foo
, hago git merge -X theirs develop
que funciona. Cuando lo hago dos veces para verificarlo, ya estoy Already up-to-date
.
Pero luego cuando me git rebase develop
para asegurarme de que foo
git rebase develop
atrapado obtengo conflictos de fusión. ¿Por qué es esto cuando git merge -X theirs develop
the merge debería tener todo el código de develop
actualizado en branch foo
?
Rebase y fusión hacen cosas muy diferentes.
Cuando ejecutas git merge develop
le estás diciendo a Git que:
HEAD
). Esto tiene algo de ID hash. develop
. Esto tiene algo de ID hash. Rastree el gráfico de compromiso para encontrar la confirmación básica de fusión de los antepasados comunes de las dos confirmaciones identificadas en los pasos 1 y 2:
...--o--B--o--1 <-- somebranch (HEAD) \ o--o--2 <-- develop
Compara (como en git diff
) la base de combinación para cometer # 1.
-X theirs
hace una diferencia: si hay conflictos de fusión en las dos diferencias, Git prefiere "su" cambio. Tenga en count que para cualquier parte de un solo file que muestra dos cambios diferentes pero no conflictivos, Git aún toma ambos cambios.) Aplica el resultado al tree en la base de fusión. Realiza una nueva confirmación de tipo "fusionar compromiso", con los padres n.º 1 y n.º 2 (en ese order) en la sucursal actual:
...--o--B--o--1---M <-- somebranch (HEAD) \ / o--o--2 <-- develop
Si ahora ejecuta la misma git merge
nuevamente, Git encuentra M
y 2
, encuentra su base de combinación (que no es B
esta vez sino 2
) y declara que no hay nada que hacer: la base de fusión ya es una de las dos confirmaciones .
Cuando ejecutas git rebase develop
estás diciendo a Git que:
Haga una list de todas las confirmaciones accesibles desde la sugerencia de sucursal actual ( M
, una vez realizada esta fusión) que no son alcanzables desde la confirmación identificada por develop
(commit # 2):
...--o--B--o*-1*--M <-- somebranch (HEAD) \ / o--o--2 <-- develop
Marqué estos commits con *
. Nota: M
también se puede alcanzar desde M
pero no desde 2
; pero git rebase
deliberadamente descarta todas las fusiones, ya que no tiene sentido tratar de volver a establecer una fusión.
Usando el modo "HEAD desconectado", copie (vea a continuación) las confirmaciones marcadas, colocando las nuevas copys después de que se desarrolle el compromiso identificado por el nombre:
...--o--B--o*-1*--M <-- somebranch \ / o--o--2 <-- develop \ o*'--1*' <-- HEAD
Después de todas las copys realizadas con éxito (incluida la resolución de cualquier conflicto de fusión), elimine la label de somebranch
de donde sea que esté ahora y colóquela al final de las confirmaciones copydas:
...--o--B--o--1---M [abandoned] \ / o--o--2 <-- develop \ o'--1' <-- somebranch (HEAD)
Para copyr un commit, Git esencialmente (y a veces literalmente) ejecuta git cherry-pick
en él. La operación de selección de cereza es en sí misma el "tipo de verbo" de la fusión (con una base de fusión un tanto peculiar, y "nuestra" y "de ellos" también puede ser confusa; vea comentarios). Por lo tanto, cada una de estas copys, independientemente de la cantidad de confirmaciones que se copien, puede tener conflictos de combinación. Cualquier resolución que hagas en M
se ignorará (naturalmente, dado que M
se ignora).