61 votes

git rebase interactive: la fusion de squash s'engage ensemble

Je voulais avoir une solution simple à la courge deux de fusion s'engage pendant un rebase interactif.

Mon référentiel ressemble:

   X --- Y --------- M1 -------- M2 (my-feature)
  /                 /           /
 /                 /           /
a --- b --- c --- d --- e --- f (stable)

C'est, j'ai un my-feature de la branche qui a été fusionnée à deux reprises récemment, sans vraiment s'engage entre les deux. Je ne veux pas de rebase l' my-feature de la branche depuis qu'il est publié de la direction de son propre, je veux juste de courge les deux dernières fusion s'engage dans un (n'ai pas publié ces commet encore)

J'ai essayé:

git rebase -p -i M1^

Mais j'ai eu:

Refusing to squash a merge: M2

Ce que j'ai finalement fait est:

git checkout my-feature
git reset --soft HEAD^  # remove the last commit (M2) but keep the changes in the index
git commit -m toto      # redo the commit M2, this time it is not a merge commit
git rebase -p -i M1^    # do the rebase and squash the last commit
git diff M2 HEAD        # test the commits are the same

Maintenant, la nouvelle fusion s'engager n'est pas considéré comme une opération de fusion s'engager plus (il n'a gardé que le premier parent). Donc:

git reset --soft HEAD^               # get ready to modify the commit
git stash                            # put away the index
git merge -s ours --no-commit stable # regenerate merge information (the second parent)
git stash apply                      # get the index back with the real merge in it
git commit -a                        # commit your merge
git diff M2 HEAD                     # test that you have the same commit again

Mais cela peut devenir compliqué si j'ai beaucoup s'engage, avez-vous une meilleure solution ? Merci.

Mildred

59voto

Matt Points 101

C'est un vieux sujet, mais j'ai juste couru à travers elle, tout en recherchant des informations similaires.

Un truc similaire à celle décrite dans la sous-Arborescence de poulpe de fusion est vraiment une bonne solution pour ce type de problème:

git checkout my-feature
git reset --soft Y
git rev-parse f > .git/MERGE_HEAD
git commit

Qui va prendre l'indice tel qu'il existe à l'extrémité de ma-fonction, et l'utiliser pour créer un nouveau commit hors de Y, avec " f " comme une deuxième mère. Le résultat est le même que si vous n'avais jamais effectué de M1, mais allé directement à l'exécution M2.

8voto

bobDevil Points 5986

si vous n'avez pas publié les deux derniers validations de fusion, vous pouvez effectuer une réinitialisation et une fusion simple.

 git reset --hard Y
git merge stable
 

5voto

Je suis venu sur ce sujet en voulant écraser un seul commit de fusion; donc ma réponse n'est pas très utile à la question d'origine.

                X
                \   
                 \  
a --- b --- c --- M1 (subtree merge)
 

Ce que je voulais, c'était rebaser la fusion M1 et tout écraser en un seul commit au-dessus de b.

 a --- b --- S (include the changes from c, X and M1)
 

J'ai essayé toutes sortes de combinaisons différentes mais c'est ce qui a fonctionné:

 git checkout -b rebase b (checkout a working branch at point b)
git merge --squash M1
 

Cela appliquera les modifications dans l'index où elles peuvent être validées git commit

1voto

Michael Wild Points 6612

Aucune des méthodes mentionnées ne fonctionne pour moi avec une version récente de git. Dans mon cas, ce qui suit a fait l'affaire:

 git reset --soft Y
git reset --hard $(git commit-tree $(git write-tree) -p HEAD -p stable < commit_msg)
 

Cependant, vous devrez d'abord écrire le message de validation dans le fichier commit_msg.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X