Cambiar la base de un commit de Git merge


Tomemos el siguiente caso:

Tengo algo de trabajo en una rama temática y ahora estoy listo para fusionar de nuevo con master:

* 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ó algún tiempo, así que hago otra búsqueda y me doy cuenta de 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 intento 'git rebase origin / master' desde master, me veo obligado a resolver todos los conflictos de nuevo, y también pierdo la fusión commit:

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

¿Hay una forma limpia de cambiar la base de la confirmación de fusión para que termine 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
Author: jipumarino, 2011-01-24

5 answers

Hay dos opciones aquí.

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

Otra es usar la opción -p en git rebase, que se describe como sigue en el manual: "En lugar de ignorar las fusiones, intente recrearlas."Esta pregunta lo explica aún más: ¿Qué hace exactamente" rebase preserve preserve-merges " de git (y por qué?)

 97
Author: siride,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:36

Ok, esa es una vieja pregunta y ya han aceptado respuesta por @siride, pero esa respuesta no fue suficiente en mi caso, ya que --preserve-merges te obliga a resolver todos los conflictos por segunda vez. Mi solución basada en la idea de @Tobi B pero con instrucciones exactas paso a paso

Así que vamos a empezar en tal estado basado en el ejemplo en la pregunta:

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

Ten en cuenta que tenemos 2 commits por delante master, así que cherry-pick no funcionaría.

  1. En primer lugar, vamos a crear la historia correcta que queremos:

    git checkout -b correct-history # create new branch to save master for future
    git rebase -s ours -p origin/master
    

    -p significa --preserve-merges, lo usamos para guardar nuestra confirmación de fusión en el historial -s ours significa --strategy=ours, lo usamos para ignorar todos los conflictos de fusión ya que no nos importa qué contenido habrá en esa confirmación de fusión, solo necesitamos un buen historial ahora.

    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. Vamos a obtener el índice correcto ahora.

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

    Podemos obtener algunos conflictos de fusión adicionales aquí, pero eso solo sería conflictos de archivos cambiados entre 8101fe3 y f5a7ca8, pero no incluye conflictos ya resueltos de topic

    La historia se verá así (ignorando la historia correcta):

    *   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 historial correcto y rama con índice correcto

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

    Usamos reset --soft para restablecer nuestra rama (e historial) a correct-history, pero dejamos el índice y el árbol de trabajo como están. Luego usamos commit --amend para reescribir nuestra confirmación de fusión, que solía tener un índice incorrecto, con nuestro buen índice de master.

    Al final tendremos tal estado (note otro id de la confirmación superior):

    *   13e6d03 Merge branch 'topic'  [HEAD -> master]
    |\  
    | * b62cae6 2                     [topic]
    * | f5a7ca8 5                     [origin/master]
    * | e7affba 4
    * | eb3b733 3
    |/  
    * 38abeae 1
    
 12
Author: Ivan Naydonov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 10:36:36

Dado que acabo de perder un día tratando de resolver esto y en realidad encontré una solución con la ayuda de un compañero de trabajo, pensé que debería intervenir.

Tenemos una base de código grande y tenemos que lidiar con 2 ramas fuertemente modificadas al mismo tiempo. Hay una rama principal y una rama secundaria si usted cuál.

Mientras combino la rama secundaria en la rama principal, el trabajo continúa en la rama principal y para cuando termine, no puedo empujar mis cambios porque son incompatible.

Por lo tanto necesito "rebase" mi "merge".

Así es como finalmente lo hicimos:

1) toma nota del SHA. ex.: c4a924d458ea0629c0d694f1b9e9576a3ecf506b

git log -1

2) Cree el historial apropiado pero esto romperá la fusión.

git rebase -s ours --preserve-merges origin/master

3) toma nota del SHA. ex.: 29dd8101d78

git log -1

4) Ahora vuelve a donde estabas antes

git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard

5) Ahora fusiona el maestro actual en tu rama de trabajo

git merge origin/master
git mergetool
git commit -m"correct files

6) Ahora que usted tener los archivos correctos, pero el historial incorrecto, obtener el correcto historia en la parte superior de su cambio con:

git reset 29dd8101d78 --soft

7) Y luego amend modifique los resultados en su confirmación de fusión original

git commit --amend

Voila!

 3
Author: Claude Peloquin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-14 16:53:25

Parece que lo que quieres hacer es eliminar tu primera fusión. Puede seguir el siguiente procedimiento:

git checkout master      # Let's make sure we are on master branch
git reset --hard master~ # Let's get back to master before the merge
git pull                 # or git merge remote/master
git merge topic

Eso te daría lo que quieres.

 1
Author: Antoine Pelisse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 18:10:57
  • Desde tu confirmación de fusión
  • Cherry-elige el nuevo cambio que debería ser fácil
  • copia tus cosas
  • rehaga la fusión y resuelve los conflictos simplemente copiando los archivos de tu copia local;)
 0
Author: Tobi B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-30 16:26:45