Rebaser un commit de fusion Git

Prenons le cas suivant:

J’ai du travail dans une twig thématique et je suis maintenant prêt à fusionner pour maîsortingser:

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

J’effectue la fusion à partir du maître, résous les conflits et maintenant j’ai:

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

Maintenant, la fusion m’a pris du temps, alors je fais une autre recherche et remarquez que la twig principale distante a de nouvelles modifications:

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

Si j’essaie “git rebase origin / master” à partir de master, je suis obligé de résoudre à nouveau tous les conflits, et je perds aussi le commit de fusion:

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

Existe-t-il un moyen propre de rebaser la validation de la fusion et je me retrouve donc avec un historique similaire à celui que je montre ci-dessous?

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

    Il y a deux options ici.

    L’une consiste à faire un rebase interactif et à éditer le commit de fusion, à refaire la fusion manuellement et à continuer le rebase.

    Une autre consiste à utiliser l’option -p sur git rebase , décrite comme suit dans le manuel: “Au lieu d’ignorer les fusions, essayez de les recréer”. Cette question l’explique plus en détail: qu’est-ce que fait exactement “rebase –preserve-merges” de git (et pourquoi?)

    Ok, c’est une vieille question et elle a déjà accepté la réponse de @siride , mais cette réponse n’était pas suffisante dans mon cas, car --preserve-merges vous oblige à résoudre tous les conflits une deuxième fois. Ma solution basée sur l’idée de @Tobi B mais avec des commandes précises pas à pas

    Nous allons donc commencer sur un tel état basé sur l’exemple de la question:

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

    Notez que nous avons 2 commits avant maître, donc la sélection de cerises ne fonctionnerait pas.

    1. Tout d’abord, créons une histoire correcte que nous voulons:

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

      -p signifie --preserve-merges , nous l’utilisons pour sauvegarder notre fusion commit dans history -s ours signifie --strategy=ours , nous l’utilisons pour ignorer tous les conflits de fusion car nous ne nous soucions pas du contenu fusion commit, nous avons seulement besoin de belle histoire maintenant.

      L’histoire ressemblera à ça (en ignorant le maître):

       * 51984c7 Merge branch 'topic' [HEAD -> correct-history] |\ | * b62cae6 2 [topic] * | f5a7ca8 5 [origin/master] * | e7affba 4 * | eb3b733 3 |/ * 38abeae 1 
    2. Allons obtenir un index correct maintenant.

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

      Nous pouvons obtenir des conflits de fusion supplémentaires ici, mais cela ne serait que des conflits de fichiers modifiés entre 8101fe3 et f5a7ca8 , mais ne comprend pas les conflits déjà résolus du topic

      L’histoire ressemblera à ceci (en ignorant l’historique correct):

       * 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 dernière étape consiste à combiner notre twig avec l’historique correct et la twig avec l’index correct

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

      Nous utilisons reset --soft pour réinitialiser notre twig (et notre historique) pour corriger l’historique, mais laissez l’index et l’arborescence de travail tels reset --soft . Ensuite, nous utilisons commit --amend pour réécrire notre commit de fusion, qui avait un index incorrect, avec notre bon index de master.

      Au final, nous aurons un tel état (notez un autre identifiant de la validation top):

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

    Étant donné que je viens de perdre une journée à essayer de comprendre cela et à trouver une solution avec l’aide d’un collègue, j’ai pensé que je devrais le faire.

    Nous avons une base de code volumineuse et nous devons faire face à 2 twigs fortement modifiées en même temps. Il y a une twig principale et une twig secondaire si vous le souhaitez.

    Alors que je fusionne la twig secondaire dans la twig principale, le travail continue dans la twig principale et au moment où je le fais, je ne peux pas pousser mes modifications car elles sont incompatibles.

    Je dois donc “rebaser” mon “fusion”.

    Voici comment nous l’avons finalement fait:

    1) notez le SHA. ex .: c4a924d458ea0629c0d694f1b9e9576a3ecf506b

     git log -1 

    2) Créez l’historique approprié, mais cela brisera la fusion.

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

    3) notez le SHA. ex .: 29dd8101d78

     git log -1 

    4) Maintenant, réinitialisez-vous là où vous étiez avant

     git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard 

    5) Fusionner maintenant le maître actuel dans votre twig de travail

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

    6) Maintenant que vous avez les bons fichiers, mais le mauvais historique, obtenez la bonne histoire en plus de votre changement avec:

     git reset 29dd8101d78 --soft 

    7) Et puis –amender les résultats dans votre commit de fusion d’origine

     git commit --amend 

    Voila!

    Il semble que ce que vous voulez faire est de supprimer votre première fusion. Vous pouvez suivre la procédure suivante:

     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 

    Cela vous donnerait ce que vous voulez.

    • De votre engagement de fusion
    • Cherry-pick le nouveau changement qui devrait être facile
    • copier vos affaires
    • refaire la fusion et résoudre les conflits en copiant simplement les fichiers de votre copie locale;)