Rebasar una confirmación de fusión de Git

Resuelto jipumarino asked hace 13 años • 5 respuestas

Tomemos el siguiente caso:

Tengo algo de trabajo en una rama temática y ahora estoy listo para volver a fusionarme con el maestro:

* eb3b733 3     [master] [origin/master]
| * b62cae6 2   [topic]
|/  
* 38abeae 1

Realizo la fusión desde master, resuelvo los conflictos y ahora tengo:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | eb3b733 3                     [origin/master]
|/  
* 38abeae 1

Ahora, la fusión me llevó algo de tiempo, así que hago otra búsqueda y noto que la rama maestra remota tiene nuevos cambios:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
| | * e7affba 4                   [origin/master]
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

Si lo intento git rebase origin/masterdesde el maestro, me veo obligado a resolver todos los conflictos nuevamente y también pierdo el compromiso de fusión:

* d4de423 2       [master]
* e7affba 4       [origin/master]
* eb3b733 3
| * b62cae6 2     [topic]
|/  
* 38abeae 1

¿Existe una manera limpia de cambiar la base de la confirmación de fusión para terminar con un historial como el que muestro a continuación?

*   51984c7 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | e7affba 4                     [origin/master]
* | eb3b733 3
|/  
* 38abeae 1
jipumarino avatar Jan 24 '11 22:01 jipumarino
Aceptado

Aquí hay dos opciones.

Una es hacer una rebase interactiva y editar la confirmación de fusión, rehacer la fusión manualmente y continuar con la rebase.

Otra es utilizar la --rebase-mergesopción on git rebase, que se describe a continuación en el manual:

De forma predeterminada, una rebase simplemente eliminará las confirmaciones de fusión de la lista de tareas pendientes y colocará las confirmaciones rebasadas en una única rama lineal. Con --rebase-merges, la rebase intentará preservar la estructura de ramificación dentro de las confirmaciones que se van a rebasar, recreando las confirmaciones de fusión. Cualquier conflicto de fusión resuelto o modificación manual en estas confirmaciones de fusión deberá resolverse o volverse a aplicar manualmente. "

siride avatar Jan 24 '2011 16:01 siride

Ok, es una pregunta antigua y ya tiene una respuesta aceptada por @siride, pero esa respuesta no fue suficiente en mi caso, ya que --preserve-mergeste obliga a resolver todos los conflictos por segunda vez. Mi solución se basa en la idea de @Tobi Bpero con comandos exactos paso a paso.

Comenzaremos en el mismo estado que se encuentra en la pregunta original:

*   8101fe3 Merge branch 'topic'  [HEAD -> master]
|\  
| * b62cae6 2                     [topic]
| |
| | * f5a7ca8 5                   [origin/master]
| | * e7affba 4
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

Tenga en cuenta que tenemos 2 confirmaciones por delante del maestro, por lo que la selección selectiva no funcionará.

  1. Primero que nada, creemos el historial correcto:

     git checkout -b correct-history # create new branch to save master for future
     git rebase --strategy=ours --preserve-merges origin/master
    

    Usamos --preserve-mergespara guardar nuestro compromiso de fusión en el historial. Solemos --strategy=oursignorar todos los conflictos de fusión, ya que no nos importa el contenido de esa confirmación fusionada, solo necesitamos un buen historial.

    La historia se verá así (ignorando al maestro):

     *   51984c7 Merge branch 'topic'  [HEAD -> correct-history]
     |\  
     | * b62cae6 2                     [topic]
     * | f5a7ca8 5                     [origin/master]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    
  2. Consigamos el índice correcto ahora.

     git checkout master # return to our master branch
     git merge origin/master # merge origin/master on top of our master
    

    Es posible que obtengamos algunos conflictos de fusión adicionales aquí, pero solo serían conflictos de archivos modificados entre 8101fe3y f5a7ca8, no incluye conflictos ya resueltos detopic

    El historial se verá así (ignorando el historial correcto):

     *   94f1484 Merge branch 'origin/master'  [HEAD -> master]
     |\  
     * | f5a7ca8 5                   [origin/master]
     * | e7affba 4
     | *   8101fe3 Merge branch 'topic'
     | |\  
     | | * b62cae6 2                     [topic]
     |/ /
     * / eb3b733 3
     |/  
     * 38abeae 1
    
  3. La última etapa es combinar nuestra rama con el historial correcto y la rama con el índice correcto.

     git reset --soft correct-history
     git commit --amend
    

    Solemos reset --softrestablecer nuestra rama (y nuestro historial) al historial correcto, pero dejamos el índice y el árbol de trabajo como están. Luego usamos commit --amendpara reescribir nuestra confirmación de fusión, que solía tener el índice incorrecto, con nuestro buen índice del maestro.

    Al final tendremos este estado (tenga en cuenta otra identificación del compromiso superior):

     *   13e6d03 Merge branch 'topic'  [HEAD -> master]
     |\  
     | * b62cae6 2                     [topic]
     * | f5a7ca8 5                     [origin/master]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    
Ivan Naydonov avatar Dec 14 '2017 17:12 Ivan Naydonov