4897 votes

Annuler une fusion Git ?

Dans ma branche master, j'ai fait un git merge some-other-branch localement, mais n'a jamais poussé les changements vers le master d'origine. Je n'avais pas l'intention de fusionner, donc j'aimerais l'annuler. En faisant une git status après ma fusion, je recevais ce message :

# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.

Sur la base de quelques instructions que j'ai trouvées J'ai essayé d'exécuter

git revert HEAD -m 1

mais maintenant je reçois ce message avec git status :

# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.

Je ne veux pas que ma branche soit en avance d'un nombre quelconque de commits. Comment puis-je revenir à ce point ?

3 votes

Si vous avez besoin de préserver l'histoire, en d'autres termes, il y a un changement que quelqu'un vous a arraché ou que vous avez poussé quelque part, utilisez la solution dans la réponse de Yuri Ushakov ci-dessous !

6 votes

Veuillez désélectionner la réponse gagnante actuelle, elle n'est pas sûre (comme beaucoup l'ont fait remarquer) mais continue à recueillir des votes. Pour moi, "MBO"-s semble la meilleure, bien qu'elle ait beaucoup moins de points.

5 votes

Si vous devez préserver l'histoire utiliser Yuri La solution de l'entreprise ci-dessous ! (j'ajoute simplement un lien vers le commentaire de @Sedrik)

5526voto

Marcin Gil Points 16951

Avec git log vérifier quel commit est celui qui précède la fusion. Ensuite, vous pouvez le réinitialiser en utilisant :

git reset --hard commit_sha

Il y a aussi un autre moyen

git reset --hard HEAD~5

vous permettra de récupérer 5 engagements.

Comme @Velmont l'a suggéré dans sa réponse ci-dessous, dans ce cas direct, utiliser :

git reset --merge ORIG_HEAD

pourrait donner de meilleurs résultats, car elle devrait préserver vos modifications. Ici, ORIG_HEAD devrait pointer vers un commit directement avant que la fusion ne se produise.

Citant la documentation de l --merge interrupteur :

--merge

Réinitialise l'index et met à jour les fichiers de l'arbre de travail qui sont différents entre <commit> et HEAD, mais conserve ceux qui sont différents entre l'index et l'arbre de travail (c'est-à-dire qui ont des modifications qui n'ont pas été ajoutées).

147 votes

Je ne pense pas que cela fonctionnera (toujours ?) -- le "one prior the merge" sera le commit le plus récent qui a été fusionné depuis l'autre branche -- ce ne sera pas le commit le plus récent sur la branche actuelle. N'est-ce pas ? (Cela pourrait juste être un résultat de ce que git log choisit de montrer par défaut -- peut-être y a-t-il une sortie différente de git log ou git reflog pourrait être utilisé pour cela)

6 votes

Je pense que ça peut dépendre si vous écrasez la fusion.

1 votes

Dans mon cas, git log montre un commit de fusion et liste les deux commits parents qui ont été fusionnés pour aboutir au commit de fusion. J'ai utilisé git log pour déterminer lequel des commits parents listés appartenait à la branche dans laquelle j'ai fusionné avec la branche courante, puis j'ai réinitialisé l'autre commit (puisque cela devait être le HEAD de la branche courante avant la fusion). Je me méfierais de l'utilisation de la fonction HEAD~# puisque vous ne savez probablement pas combien de commits ont été apportés avec la fusion.

1712voto

randomguy3 Points 8307

En supposant que votre maître local n'était pas en avance sur origin/master, vous devriez être en mesure de faire

git reset --hard origin/master

Alors, votre local master devrait être identique à origin/master .

83 votes

@Carter ce n'est pas la meilleure réponse. Il est possible que origin/master soit en avance de quelques commits sur votre master local juste avant la fusion, dans ce cas, cela pourrait ne pas donner les résultats souhaités.

16 votes

@dhruva-sagar Oui, mais tant que git ne dit pas que vous êtes en retard, et que vous ne faites pas de fetch, tout devrait bien se passer.

0 votes

C'est très bien, mais si vous avez fait une fusion automatique à distance (par exemple, fusionner une demande de pull sur github), alors vous devrez réinitialiser à un commit (réponse acceptée).

1250voto

Yuri Ushakov Points 5971

Voir chapitre 4 dans le livre git et le message original de Linus Torvalds .

Pour annuler une fusion qui a déjà été poussé :

git revert -m 1 commit_hash

Assurez-vous de revenir en arrière si vous soumettez à nouveau la branche, comme Linus l'a dit.

10 votes

@perfectionist d'accord :) J'aimerais qu'il y ait un moyen de migrer cette réponse vers une autre question (peut-être y en a-t-il un ?).

0 votes

pour plus d'informations sur le retour en arrière : lien

3 votes

Pour être sûr que ce revert a fonctionné, vous pouvez faire git diff hash1 hash2 où hash1 est le commit revert, et hash2 est l'ancien commit dont vous essayez de retrouver l'état. Pas de sortie == succès ! J'ai été capable de revenir en arrière sur plusieurs commits en faisant cela plusieurs fois, en commençant par inverser la fusion la plus récente et en travaillant en arrière. git diff m'a montré que je me suis retrouvé dans l'état que je voulais.

1161voto

Velmont Points 2322

Il est étrange que la commande la plus simple soit absente. La plupart des réponses fonctionnent, mais défaire la fusion que vous venez de faire, c'est le moyen le plus simple et le plus sûr :

git reset --merge ORIG_HEAD

L'arbitre ORIG_HEAD pointera vers le commit original d'avant la fusion.

(le --merge n'a rien à voir avec la fusion, c'est tout comme git reset --hard ORIG_HEAD mais plus sûr puisqu'il ne touche pas aux changements non validés)

20 votes

Si vous avez sali votre arbre de travail depuis, git reset --merge ORIG_HEAD préserve ces changements.

5 votes

C'est le uniquement réponse correcte (je ne dis pas que c'est la meilleure réponse - notez la différence). Disons que, sur master, j'ai fait 3 commits à t1, t3, et t5. Disons que, sur branch1, j'ai fait 3 commentaires à t2, t4 et t6 (supposons que t1, t2, t3, t4, t5 et t6 sont dans l'ordre chronologique). Toute commande similaire à git reset --hard HEAD~5 ne réinitialisera que HEAD (peut supprimer des commits à la fois dans master et branch1). Seul le --merge supprime l'option merge .

4 votes

@Manu Le --merge ne supprime pas réellement la fusion, vous pouvez utiliser l'option --hard il fonctionnera également bien. C'est la référence ORIG_HEAD qui est l'indice ici, elle est définie avant que vous fassiez une fusion à l'endroit où vous vous trouvez à ce moment-là :)

489voto

Travis R Points 8935

Avec les nouvelles versions de git, vous pouvez simplement faire :

git merge --abort

19 votes

Sa fusion est validée mais pas poussée (voir le titre), il a déjà fusionné, votre commande ne fonctionne que lorsqu'il est encore au milieu d'une fusion.

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