git: a dónde se va el conflicto cuando se rebase

Supongamos que tengo un historial de compromiso como este

master | |A| -> |B| -> |E| | |C| -> |D| | hotfix 

Supongamos que commit E y D tienen conflictos. Ahora, según los documentos , después de una rebase

 $> git checkout hotfix $> git rebase master # fix conflicts $> git add -A $> git rebase --continue $> git push --force # rewrite history of branch hotfix on remote 

Voy a terminar con

  master | |A| -> |B| -> |E| | |C| -> |D| | hotfix 

Sin embargo, no veo a dónde van mis resultados de fusión / conflicto? Si vuelvo a basarme

 $> git rebase master 

No espero volver a tener los mismos conflictos otra vez, ¿verdad?

Pregunta final, si el compromiso D fuera antes del compromiso E, ¿el diagtwig que mostré arriba (resultado después de la rebase) seguirá siendo el mismo?

Sin embargo, no veo a dónde van mis resultados de fusión / conflicto?

Cuando rebase git almacena los objects provisionales en un área temporal bajo el directory .git . (Por ejemplo, .git/rebase-merge .) Si hay conflictos, se le pedirá que los resuelva en el process de hacer la rebase.

Si vuelvo a basarme … no espero volver a tener los mismos conflictos, ¿verdad?

No, no volverás a tener los mismos conflictos porque los resolviste en tu anterior (primera) revisión.

Pregunta final, si el compromiso D fuera antes del compromiso E, ¿el diagtwig que mostré arriba (resultado después de la rebase) seguirá siendo el mismo?

Sí, siempre que C y D fueran el resultado, seguiría siendo el mismo, en el sentido de que se aplicarían en la parte superior de E , la punta del maestro, pero en ambos casos no sería exactamente el diagtwig que dibujarías. La principal diferencia es que las confirmaciones serían D' y C' , serán nuevas confirmaciones, incluso si son completamente idénticas a D y C , en el caso de que no haya conflictos de rebase.

Cuando haces una rebase, lo que estás haciendo que Git haga "debajo de las sábanas" es en realidad una serie de selects de cereza. Es mucho más obvio si label las confirmaciones de manera diferente: llamemos a las "nuevas" versiones de C y D , C' y D' lugar. Y dejemos a los viejos allí, pero "abandonados" (perdidos y solos, por así decirlo). Así que comenzamos con esto (he invertido las flechas desde que los puntos de confirmación se dirigen a sus confirmaciones principales, no a sus hijos: E tiene B como padre, D tiene C , C tiene B y B tiene A ):

 A <-- B <-- E <-- master ^ \ C <-- D <-- hotfix 

Para hacer la rebase, git cherry-picks confirma C , haciendo nueva C' con E como su padre; luego elige con precisión D , con la intención de hacer una nueva D' con C' como su padre. Hay un conflicto en este punto (como dijiste) por lo que todo el process se detiene y te hace resolver el conflicto y continuar. Esto finalmente hace D' y luego git reescribe la label de la hotfix para apuntar a D' :

 A <-- B <-- E <-- master ^ ^ | \ C - D \ \ C' <-- D' <-- hotfix 

Los viejos commits, C y D , en realidad siguen ahí (pero sin label de bifurcación, aunque todavía hay una reference a ellos en el reflog de la bifurcación de hotfix , y temporalmente, rebase deja una label especial deletreada ORIG_HEAD apuntando a D ). Es solo que cuando mira para ver qué hay "en la hotfix bifurcación", ahora verá las confirmaciones copydas.

La resolución de conflicto que aplicó está en el tree adjunto para confirmar D' (ya que es allí donde se produjo el conflicto y lo solucionó manualmente). Si desenterras el ID de compromiso para D , o usas el reflog o ORIG_HEAD , puedes diferenciar los treees para D y D' para ver lo que hiciste:

 $ git diff ORIG_HEAD hotfix 

por ejemplo. (Pero esto también incluye los cambios en E , por lo que probablemente también sea engañoso).

(Cada selección de cereza está hecha, en términos generales, al diferir el tree de commit a ser recogido con el tree de sus padres, y luego aplicar ese diff como un parche al commit al que se está agregando el "cherry". elige C y agrégalo a E para get C' , git diffs B y C Luego, para seleccionar con precisión D , git diffs C y D , aplicando la diferencia a C' esta vez. Por lo tanto, el tree para D no contendrá cualquier línea de E pero el tree para D' probablemente lo hará).