¿Por qué puede fallar una rebase inmutable?

Tengo un repo de git con bastante historia por ahora. Estaba tratando de hacer algunos cambios en los compromisos iniciales y encontré conflictos extraños.

Descubrí que si hago un git rebase COMMIT ^ y elijo uno de los primeros, pero luego en la list no toco nada, como elegir todos los commits, sigue con los movimientos, reproduce todos los commits y es inexplicable para mí, falla en algunos.

¿Cómo es esto posible? Si el historial no se modifica porque se seleccionan todas las confirmaciones, ¿cómo puede fallar?

Una rebase funciona "reproduciendo" los cambios en cada diff, haciendo nuevos commits (dejando los viejos intactos, pero escondidos, y sujetos a una eventual caducidad). El método por el cual se "reproduce" un compromiso está disponible más directamente como git cherry-pick , por lo que lo describiré primero.

Hacer una selección de cereza implica extraer los cambios realizados en una confirmación. La diferencia resultante se puede aplicar a ("parcheado") en alguna otra confirmación (diferente), utilizando el context incluido en la diferencia. Pero, como una confirmación no se almacena como cambios, cada confirmación es una "instantánea" completa de la fuente , Cherry-Pick tiene que calcular los cambios provistos por una confirmación. Lo hace comparando el compromiso con su compromiso principal.

Esto funciona bien para la historia lineal, pero no tan bien cuando hay fusiones. En particular, una fusión de compromiso tiene, por definición, al less dos padres (las fusiones con más de dos padres son inusuales pero Git lo permite). Dado un compromiso con dos padres, y no hay una manera obvia de elegir qué padre considerar al hacer una diferencia, git cherry-pick simplemente se detiene con una queja. Te hace proporcionar, con la opción -m , el padre que te importa cuando seleccionas una confesión de fusión.

El command rebase toma un enfoque diferente: por defecto, elimina las fusiones por completo, con la esperanza de que no sean necesarias. Si las fusiones importan (como aparentemente lo hacen aquí), esto dará como resultado errores en las selects de cereza.

El command rebase tiene una opción -p (aka --preserve-merges ). En este caso, intenta mantener las fusiones. En este caso particular, donde está reproduciendo una secuencia de confirmación en la confirmación básica original, una rebase de preservación de fusión debería funcionar.

Ver la documentation para más detalles.