Annuler une fusion Git qui n'a pas encore été poussée

3946

Dans ma branche master, j'ai fait un git merge some-other-branchlocalement, mais je n'ai jamais poussé les changements vers master d'origine. Je ne voulais pas fusionner, donc j'aimerais l'annuler. En faisant un git statusaprès ma fusion, je recevais ce message:

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

Sur la base de certaines instructions que j'ai trouvées , j'ai essayé de lancer

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 succursale soit en avance d'un certain nombre de commits. Comment revenir à ce point?

Matt Huggins
la source
3
Si vous avez besoin de préserver l'histoire, en d'autres termes, il y a un changement que quelqu'un vous a déjà retiré ou que vous l'avez poussé quelque part, utilisez la solution dans la réponse de Yuri Ushakov ci-dessous!
Sedrik
6
Veuillez désélectionner la réponse gagnante actuelle, elle n'est pas sûre (comme beaucoup l'ont souligné), mais elle recueille toujours des votes. Pour moi, "MBO" -s semble le meilleur, bien qu'il ait beaucoup moins de points.
inger
5
Si vous devez préserver l'historique , utilisez la solution de Yuri ci-dessous ! (ajout d'un lien vers le commentaire @Sedrik)
cregox
3
Ceci est une excellente ressource directement de Github: Comment annuler (presque) n'importe quoi avec Git
jasonleonhard

Réponses:

4461

Avec git reflogcheck, quel commit est un avant la fusion ( git reflogsera une meilleure option que git log). Ensuite, vous pouvez le réinitialiser en utilisant:

git reset --hard commit_sha

Il y a aussi une autre façon:

git reset --hard HEAD~1

Il vous ramènera 1 commit.

N'oubliez pas que tous les fichiers modifiés et non validés / non stockés seront réinitialisés à leur état non modifié . Pour les conserver, cachez les modifications ou voyez l' --mergeoption ci-dessous.


Comme @Velmont l'a suggéré ci-dessous dans sa réponse, en l'occurrence en utilisant:

git reset --hard ORIG_HEAD

pourrait donner de meilleurs résultats, car il devrait conserver vos modifications. ORIG_HEADpointera vers un commit directement avant que la fusion ne se produise, vous n'avez donc pas à le rechercher vous-même.


Une autre astuce consiste à utiliser le --mergecommutateur au lieu de --hardcar il ne réinitialise pas les fichiers inutilement:

git reset --merge ORIG_HEAD

--fusionner

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

Marcin Gil
la source
129
Je ne pense pas que cela fonctionnera (toujours?) - "celui avant la fusion" 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 . Droite? (Cela pourrait simplement être le résultat de ce qui git logchoisit de s'afficher par défaut - peut-être qu'il existe une sortie différente de git logou git reflogpourrait être utilisé pour cela)
John Bachir
6
Je pense que cela pourrait dépendre de la fusion de squash.
Marcin Gil
29
@JohnBachir a raison. Dans la git logsortie, vous souhaitez examiner les deux validations parentales. L'un est le dernier commit de votre branche, l'autre est le dernier commit de la branche dans laquelle vous avez fusionné. Vous voulez que git reset --hardle parent valide sur la branche dans laquelle vous avez fusionné.
Justin
7
@JohnBachir: Tant que la "fusion" n'est pas vraiment une avance rapide, elle se traduira par un nouveau commit qui se trouve en haut du journal, et ce commit a deux parents (ou plus de 2 si vous faites une pieuvre) fusionner). Si vous supprimez cette seule validation de fusion, toutes les anciennes validations issues de la fusion disparaîtront également. Pour être sûr, cependant, après une réinitialisation, git vous dira où se trouve la nouvelle tête: "HEAD est maintenant à 88a04de <message de validation>". Je regarde toujours cela pour m'assurer que je me suis retrouvé là où je m'attendais. Mon projet utilise un schéma de dénomination de branche standard pour garder les choses mémorables.
Mark E. Haase,
44
Ce que j'ai trouvé utile était de regarder "git reflog" et de chercher le dernier commit que j'ai fait dans master. Alors faitesgit reset --hard <commit_sha>
Max Williams
1456

En supposant que votre maître local n'était pas en avance sur son origine / maître, vous devriez pouvoir

git reset --hard origin/master

Ensuite, votre mastersuccursale locale devrait ressembler à origin/master.

randomguy3
la source
71
@Carter, ce n'est pas la meilleure réponse. Il est possible que l'origine / master soit en avance sur votre master local juste avant la fusion par certains commits, dans ce cas cela pourrait ne pas donner les résultats souhaités
Dhruva Sagar
15
@ dhruva-sagar Oui, mais tant que git ne dit pas que vous êtes en retard, et que vous ne récupérez pas, ça devrait aller.
Kelvin
3
Merci! C'est parfait si (et seulement si) vous avez un référentiel distant.
tomc
2
Non, ce n'est pas parfait pour cette question, voir la clause "assumer". La réponse de MBO couvre en fait ce cas, et le cas où la fusion n'est pas le seul commit local.
inger
2
Encore une fois, cet avertissement devrait peut-être entrer dans la réponse elle-même: évitez toujours de réécrire l'historique git!
cregox
1175

Voir le chapitre 4 du livre Git et le post original de Linus Torvalds .

Pour annuler une fusion déjà poussée :

git revert -m 1 commit_hash

Assurez-vous de rétablir le retour si vous recommencez la branche, comme l'a dit Linus.

Yuri Geinish
la source
10
@perfectionist était d'accord :) Type de souhait qu'il y ait un moyen de migrer cette réponse vers une autre question - (peut-être qu'il y en a?)
mikermcneil
pour plus d'informations sur le retour: lien
assaqqaf
1
Pour être sûr que ce retour a fonctionné, vous pouvez faire git diff hash1 hash2 où hash1 est le retour validé et hash2 est l'ancien commit dont vous essayez de revenir à l'état. Pas de sortie == succès! J'ai pu annuler plusieurs validations en faisant cela plusieurs fois, en commençant par annuler la fusion la plus récente et en travaillant à l'envers. git diff m'a montré que je me suis retrouvé dans l'état que je voulais.
Robert Sinton
6
Notez que cela ne résout pas réellement la question de l'affiche originale . L'affiche originale déjà utilisée git revert -m 1 <commit>. Le problème est que cela n'efface pas la fusion accidentelle qu'il a faite (et n'a pas encore poussé). Les autres réponses impliquant des réinitialisations dures sont meilleures pour le problème de l'affiche originale.
Ceci est une excellente ressource directement de Github: Comment annuler (presque) n'importe quoi avec Git
jasonleonhard
986

Il est étrange que la commande la plus simple ait été manquante. La plupart des réponses fonctionnent, mais en annulant la fusion que vous venez de faire, voici le moyen simple et sûr :

git reset --merge ORIG_HEAD

La référence ORIG_HEADpointera vers le commit d'origine d'avant la fusion.

(L' --mergeoption n'a rien à voir avec la fusion. C'est juste comme git reset --hard ORIG_HEAD, mais plus sûre car elle ne touche pas aux modifications non validées.)

odinho - Velmont
la source
17
Si vous avez sali votre arbre de travail depuis, git reset --merge ORIG_HEADconserve ces changements.
décédé le
1
C'est la seule bonne réponse (je ne dis pas que c'est la meilleure réponse - notez la différence). Disons que sur master, j'ai fait 3 commits en t1, t3 et t5. Disons que sur la branche 1, j'ai fait 3 commentaires à t2, t4 et t6 (supposons que t1, t2, t3, t4, t5 et t6 soient dans l'ordre chronologique). Toute commande similaire à git reset --hard HEAD~5ne réinitialise que HEAD (peut supprimer les validations à la fois dans master et branch1). Seule l' --mergeoption supprime le merge.
Manu Manjunath
@Manu L' --mergeoption ne supprime pas réellement la fusion, vous pouvez également l'utiliser --hardfonctionnera bien. C'est la référence ORIG_HEAD qui est l'indice ici, elle est définie avant de faire une fusion à l'endroit où vous en êtes à ce point. :)
odinho - Velmont
@yingted que voulez-vous dire par "Si vous avez sali votre arbre de travail depuis, git reset --merge ORIG_HEAD conserve ces changements." Vouliez-vous changer les fichiers après la fusion? Quoi qu'il en soit, j'ai fait la fusion, puis j'ai résolu certains conflits. Mais ensuite, je voulais réinitialiser la fusion et j'ai fait comme indiqué dans cette réponse. Tout allait bien et cela n'a pas conservé mes modifications effectuées après la fusion. Mon repo local est similaire à la position avant la fusion.
Samitha Chathuranga
La git reset --hard ORIG_HEADcommande a parfaitement fonctionné pour moi - elle a peut-être été aidée par le fait que je n'ai apporté aucune autre modification au référentiel après le local git mergeque j'essayais d'annuler. La commande réinitialise simplement l'état du référentiel à ce qu'il était avant la fusion. Merci pour le bon conseil!
bluebinary
391

Avec les nouvelles versions de Git, si vous n'avez pas encore validé la fusion et que vous avez un conflit de fusion , vous pouvez simplement faire:

git merge --abort

De man git merge:

[Ceci] ne peut être exécuté qu'après que la fusion a entraîné des conflits. git merge --abortva abandonner le processus de fusion et essayer de reconstruire l'état de pré-fusion.

Travis Reeder
la source
8
Sa fusion est validée mais pas repoussée (voir titre), il a déjà fusionné, votre commande ne fonctionne que lorsqu'il est encore au milieu d'une fusion
JBoy
135

Vous devez réinitialiser le commit précédent. Cela devrait fonctionner:

git reset --hard HEAD^

Ou même HEAD^^pour annuler ce retour en arrière. Vous pouvez toujours donner une référence SHA complète si vous n'êtes pas sûr du nombre de pas en arrière que vous devez prendre.

Si vous rencontrez des problèmes et que votre branche principale n'a pas subi de modifications locales, vous pouvez réinitialiser origin/master.

MBO
la source
5
La meilleure réponse à mon humble avis, intègre celle du PO (en supposant qu'une seule étape pour revenir en arrière, ce qui semblait être le cas dans le Q), ainsi que le raccourci de randomguy3 (qui fonctionne lorsque "votre branche principale n'a pas eu de changements locaux ")
inger
4
Vous commentateurs, @Inger et @Konstantin, pourquoi? Vous êtes venu ici après la création de ma réponse, et c'est plus correct. Il suffit souvent de monter la tête d'une étape est souvent une erreur, et vous devez réellement compter jusqu'où vous devez aller. Git est déjà prêt ORIG_HEADpour vous, pourquoi ne pas l'utiliser?
odinho - Velmont
cela réinitialisera-t-il également les modifications locales? #Veuillez mettre à jour.
CoDe
Cela a parfaitement fonctionné pour moi, réinitialiser la tête comme ça a beaucoup plus de sens que la moitié des réponses ici.
Varda Elentári du
HEAD ^ est égal à commit avant HEAD? et ^^ deux commits sont-ils antérieurs? Vous pensez que cela ne fonctionnera pas avec les fusions rapides?
Marcus Leon
87

Dernièrement, j'ai utilisé git reflogpour aider à cela. Cela ne fonctionne généralement que si la fusion JUST s'est produite, et c'était sur votre machine.

git reflog pourrait renvoyer quelque chose comme:

fbb0c0f HEAD@{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting

La première ligne indique qu'une fusion s'est produite. La 2ème ligne est le temps avant ma fusion. J'ai simplement git reset --hard 43b6032pour forcer cette branche à suivre avant la fusion et à continuer.

Parris
la source
Excellente réponse, merci! J'avais besoin d'annuler une fusion, mais les autres réponses ont juste gâché plus, en utilisantreflog pour obtenir le SHA et le passer en git resetfonction.
Lankymart
51

Avec Git moderne, vous pouvez:

git merge --abort

Syntaxe plus ancienne:

git reset --merge

Vieille école:

git reset --hard

Mais en réalité, il est en aperçoive une valeur qui git merge --abortest équivalente à seulement git reset --mergeétant donné que MERGE_HEADest présente. Cela peut être lu dans l'aide de Git pour la commande de fusion.

git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.

Après l'échec d'une fusion, lorsqu'il n'y a pas MERGE_HEAD , la fusion qui a échoué peut être annulée avec git reset --merge, mais pas nécessairement avec git merge --abort, donc ils ne sont pas seulement une ancienne et une nouvelle syntaxe pour la même chose .

Personnellement je trouve git reset --merge beaucoup plus puissant et utile dans le travail quotidien, c'est donc celui que j'utilise toujours.

Martin G
la source
A très bien fonctionné pour moi. Tous les autres articles disent que c'est tellement compliqué, mais cela a fait exactement ce qui était attendu. Je suppose que cela n'a fonctionné que parce qu'il y avait des conflits, ce qui ne répond pas exactement à la question d'origine.
Jeremy
Cette réponse ne se concentre pas sur la situation du PO et laisse de côté un contexte important.
Ben Wheeler
37

D'accord, les réponses que les autres personnes m'ont données étaient proches, mais cela n'a pas fonctionné. Voici ce que j'ai fait.

Ce faisant...

git reset --hard HEAD^
git status

... m'a donné le statut suivant.

# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.

J'ai ensuite dû taper git resetplusieurs fois la même commande. Chaque fois que je l'ai fait, le message a changé d'un comme vous pouvez le voir ci-dessous.

> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.

À ce stade, j'ai vu le message d'état modifié, j'ai donc essayé de faire un git pull, et cela semblait fonctionner:

> git pull
Updating 2df6af4..12bbd2f
Fast forward
 app/views/truncated |    9 ++++++---
 app/views/truncated |   13 +++++++++++++
 app/views/truncated |    2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master

En résumé, mes commandes se résumaient à ceci:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull
Matt Huggins
la source
19
ou vous auriez pu utiliserHEAD^^^^
hasen
17
peut-être même réinitialisé à origin/master;)
hasen
23

Vous pouvez utiliser git reflogpour trouver la caisse précédente. Parfois, c'est un bon état dans lequel vous souhaitez revenir.

Concrètement,

$ git reflog
$ git reset --hard HEAD@{0}
stephjang
la source
1
Je vous remercie! Vous avez sauvé une demi-journée de mon travail. Cependant, je ne pouvais pas quitter le mode reflog avec aucune commande.
Katarzyna
1
@Katarzyna utilise la touche "q" pour quitter reflog
Amjed Baig
21

Si vous êtes en train de fusionner, vous pouvez toujours l'interrompre git merge --abort

llioor
la source
2
merci bro et j'étais sur le point de faire ce truc effrayant réponse correcte. chanceux j'ai fait défiler vers le bas. je veux juste supprimer la tête de fusion
Nyuu
15

J'ai pu résoudre ce problème avec une seule commande qui n'implique pas de rechercher un ID de validation.

git reset --hard remotes/origin/HEAD

La réponse acceptée n'a pas fonctionné pour moi, mais cette commande a atteint les résultats que je cherchais.

Ralph Ritoch
la source
Exactement! Il réinitialise vos modifications sur le HEAD de la branche! Ne pas faire un par un
Carlos Zinato
n'a pas fonctionné pour moi. a fini par renvoyer une succursale locale un mois ou deux. Heureusement, tout cela est local, donc je peux toujours détruire la branche et la récupérer à nouveau. Je voulais juste le signaler au cas où d'autres essayeraient.
Matt Pengelly
@MattPengelly, cette méthode est largement non documentée et fonctionne généralement si votre branche est synchronisée avec la branche distante avant la fusion. Cela fait-il des mois que votre branche est synchronisée avec la branche distante?
Ralph Ritoch
@MattPengelly, cela dépend également de la branche vers laquelle la tête est pointée. J'utilise gitflow sur l'un de mes projets, et même si je suis sur la branche develop, les télécommandes / origin / HEAD pointent vers origin / master, donc si j'avais besoin d'annuler une fusion, je devrais probablement réinitialiser les télécommandes / origin / develop
Ralph Ritoch
14

Si vous ne l'avez pas encore validé, vous ne pouvez utiliser que

$ git checkout -f

Cela annulera la fusion (et tout ce que vous avez fait).

Idealmind
la source
J'ai essayé cela et cela a en fait augmenté le nombre de validations que ma branche locale est en avance.
barclay
14

Je suis arrivé à cette question qui cherche également à revenir à la correspondance d'origine (c.-à-d., NO s'engage avant l'origine). En recherchant plus loin, nous avons découvert qu'il existe une resetcommande pour cela:

git reset --hard @{u}

Remarque: @{u}est un raccourci pour origin/master. (Et, bien sûr, vous avez besoin de ce référentiel distant pour que cela fonctionne.)

leanne
la source
14

Vous devez changer votre HEAD, pas le vôtre bien sûr mais git HEAD ....

Donc, avant de répondre, ajoutons un peu de contexte, expliquant ce que c'est HEAD.

First of all what is HEAD?

HEADest simplement une référence au commit actuel (le plus récent) sur la branche courante.
Il ne peut y en avoir qu'un seul HEADà un moment donné. (à l'exclusion git worktree)

Le contenu de HEADest stocké à l'intérieur .git/HEADet contient les 40 octets SHA-1 de la validation en cours.


detached HEAD

Si vous n'êtes pas sur le dernier commit - ce qui signifie qu'il HEADpointe vers un commit antérieur dans l'historique, c'est appelé detached HEAD.

entrez la description de l'image ici

Sur la ligne de commande, il ressemblera à ceci - SHA-1 au lieu du nom de la branche car le HEADne pointe pas vers la pointe de la branche actuelle

entrez la description de l'image ici

entrez la description de l'image ici

Quelques options sur la façon de récupérer à partir d'une tête détachée:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Cela va extraire une nouvelle branche pointant vers le commit souhaité.
Cette commande extrait un commit donné.
À ce stade, vous pouvez créer une branche et commencer à travailler à partir de ce point.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Vous pouvez également toujours utiliser le reflog.
git reflogaffichera tout changement qui a mis à jour le HEADet vérifier l'entrée de reflog souhaitée mettra le HEADdos à ce commit.

Chaque fois que le HEAD est modifié, il y aura une nouvelle entrée dans le reflog

git reflog
git checkout HEAD@{...}

Cela vous ramènera à votre engagement souhaité

entrez la description de l'image ici


git reset --hard <commit_id>

"Déplacer" votre HEAD vers le commit souhaité.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Remarque: ( depuis Git 2.7 ),
    vous pouvez également utiliser le git rebase --no-autostash.

git revert <sha-1>

"Annuler" la validation ou la plage de validation donnée.
La commande de réinitialisation "annulera" toutes les modifications apportées au commit donné.
Un nouveau commit avec le patch d'annulation sera validé tandis que le commit d'origine restera également dans l'historique.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Ce schéma illustre quelle commande fait quoi.
Comme vous pouvez le voir, reset && checkoutmodifiez le HEAD.

entrez la description de l'image ici

CodeWizard
la source
C'est un trésor 🐱‍👤🐱‍👤🐱‍👤
Jawand Singh
12

La réponse la plus simple est celle donnée par odinho - Velmont

Tout d'abord git reset --merge ORIG_HEAD

Pour ceux qui cherchent à réinitialiser après que les modifications ont été poussées, faites cela (car c'est le premier message vu pour toutes les questions de fusion git reset)

git push origin HEAD --force

Cela sera réinitialisé de manière à ce que vous n'obteniez pas à nouveau les modifications fusionnées après le tirage.

Harsha
la source
10

Juste pour une option supplémentaire à regarder, j'ai principalement suivi le modèle de branchement décrit ici: http://nvie.com/posts/a-successful-git-branching-model/ et en tant que tel, j'ai fusionné avec--no-ff (non avance rapide) généralement.

Je viens de lire cette page car j'avais accidentellement fusionné une branche de test au lieu de ma branche de publication avec master pour le déploiement (site web, master est ce qui est en direct). La branche testing a fusionné avec deux autres branches et totalise environ six commits.

Donc, pour annuler l'ensemble du commit, j'en avais juste besoin d'un git reset --hard HEAD^et il a annulé l'ensemble de la fusion. Étant donné que les fusions n'ont pas été transmises rapidement, la fusion était un bloc et un pas en arrière est "branche non fusionnée".

Damien Byrne
la source
10

Vous ne pouvez utiliser que deux commandes pour annuler une fusion ou redémarrer par un commit spécifique:

  1. git reset --hard commitHash (vous devez utiliser la validation que vous souhaitez redémarrer, par exemple 44a587491e32eafa1638aca7738)
  2. git push origin HEAD --force (Envoi de la nouvelle branche maître locale à origin / master)

Bonne chance et allez-y!

Matheus Abreu
la source
10

Cela peut se faire de plusieurs manières.

1) Annuler la fusion

Si vous êtes entre une mauvaise fusion (effectuée par erreur avec une mauvaise branche) et que vous souhaitez éviter la fusion pour revenir à la dernière branche comme ci-dessous:

git merge --abort

2) Réinitialiser HEAD sur la branche distante

Si vous travaillez à partir de la branche de développement à distance, vous pouvez réinitialiser HEAD sur le dernier commit sur la branche à distance comme ci-dessous:

git reset --hard origin/develop

3) Supprimez la branche en cours et procédez à nouveau à la vérification du référentiel distant

Considérant que vous travaillez sur le développement d'une branche dans le référentiel local, qui se synchronise avec la branche distante / développement, vous pouvez faire comme ci-dessous:

git checkout master 
##to delete one branch, you need to be on another branch, otherwise you will fall with the branch :) 

git branch -D develop
git checkout -b develop origin/develop
Amit Kaneria
la source
que "1) Abort Merge" était assez joli. Upvoting.
CodeToLife
1
Faites attention! git merge --abort "ne peut être exécuté qu'après que la fusion a entraîné des conflits. git merge --abort abandonnera le processus de fusion et essaiera de reconstruire l'état d'avant la fusion"
Pedro García Medina
8

Si votre fusion et les validations correspondantes n'ont pas encore été poussées, vous pouvez toujours passer à une autre branche, supprimer la branche d'origine et la recréer.

Par exemple, j'ai accidentellement fusionné une branche de développement en master et j'ai voulu annuler cela. En utilisant les étapes suivantes:

git checkout develop
git branch -D master
git branch -t master origin/master

Voila! Master est au même stade que l'origine et votre état de fusion erroné est effacé.

Stephan
la source
1
Remarque: Cela annule non seulement la fusion, mais également toutes les validations locales effectuées depuis le dernier push vers l'origine.
Martijn Heemels
4

Si vous voulez une solution en ligne de commande, je suggère de simplement aller avec la réponse de MBO.

Si vous êtes un débutant, vous aimerez peut-être l'approche graphique:

  1. Démarrer gitk (à partir de la ligne de commande, ou clic droit dans le navigateur de fichiers si vous l'avez)
  2. Vous pouvez facilement repérer le commit de fusion là-bas - le premier nœud du haut avec deux parents
  3. Suivez le lien vers le premier parent / parent gauche (celui de votre branche actuelle avant la fusion, généralement rouge pour moi)
  4. Sur le commit sélectionné, cliquez avec le bouton droit sur "Réinitialiser la branche ici", choisissez la réinitialisation matérielle là-bas
en colère
la source
4

Stratégie: créer une nouvelle succursale d'où tout allait bien.

Raisonnement: annulation d'une fusion est difficile. Il existe trop de solutions, selon de nombreux facteurs, par exemple si vous avez validé ou poussé votre fusion ou s'il y a eu de nouveaux validations depuis votre fusion. Vous devez également avoir une compréhension relativement approfondie de git pour adapter ces solutions à votre cas. Si vous suivez aveuglément certaines instructions, vous pouvez vous retrouver avec une "fusion vide" où rien ne sera fusionné, et de nouvelles tentatives de fusion inciteront Git à vous dire "Déjà à jour".

Solution:

Disons que vous souhaitez fusionner devdans feature-1.

  1. Recherchez la révision dont vous souhaitez recevoir la fusion:

    git log --oneline feature-1
    a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- the merge you want to undo
    e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
    
  2. Vérifiez-le (remontez dans le temps):

    git checkout e5f6g7h8
    
  3. Créez une nouvelle branche à partir de là et vérifiez-la:

    git checkout -b feature-1
    

Vous pouvez maintenant redémarrer votre fusion:

  1. Fusionner: git merge dev

  2. Corrigez vos conflits de fusion.

  3. Commettre: git commit

  4. Lorsque vous êtes satisfait des résultats, supprimez l'ancienne branche: git branch --delete feature-1

pyb
la source
2

Il vous suffit de créer une nouvelle branche, puis de sélectionner à votre guise les engagements souhaités.

Son économiseur et plus simple réinitialise ensuite décrit dans de nombreuses réponses ci-dessus

devi
la source
1
Je suis d'accord avec cette suggestion, surtout si vous n'êtes pas entièrement à l'aise avec les commandes git répertoriées. Cela peut être plus lent avec plus de "labeur", mais si cela ne se produit pas beaucoup et que vous craignez de perdre votre travail, cela en vaut la peine.
Greg
1

Je pense que vous pouvez faire git rebase -i [hash] [branch_name] où se [hash]trouve le hachage d'identification, quelle que soit la date à laquelle vous souhaitez rembobiner plus un (ou le nombre de validations que vous souhaitez revenir), puis supprimez les lignes des validations dans l'éditeur que vous ne voulez plus . Enregistrez le fichier. Sortie. Prier. Et il devrait être rembobiné. Vous devrez peut-être faire un git reset --hard, mais cela devrait être bon à ce stade. Vous pouvez également l'utiliser pour extraire des validations spécifiques d'une pile, si vous ne souhaitez pas les conserver dans votre historique, mais cela peut laisser votre référentiel dans un état que vous ne voulez probablement pas.

tychoish
la source
1

Si vous avez validé la fusion:

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard
Dorian
la source
1
  1. Tout d'abord, assurez-vous que vous avez tout engagé.

  2. Réinitialisez ensuite votre référentiel à l'état de travail précédent:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

    ou en utilisant --hard( cela supprimera toutes les modifications locales non validées! ):

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

    Utilisez le hachage qui était là avant votre commit mal fusionné.

  3. Vérifiez les validations que vous souhaitez réengager en haut de la version correcte précédente en:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. Appliquez vos bons commits en haut de la bonne version de votre référentiel en:

    • En utilisant cherry-pick (les changements introduits par certains commits existants)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • Ou en sélectionnant la gamme de commits par:

      • Vérifiez d'abord les bons changements avant de les fusionner:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • Vérifiez d'abord les bons changements avant de les fusionner:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        où il s'agit de la plage des validations correctes que vous avez validées (à l'exclusion de la fusion incorrectement validée).

kenorb
la source
1
  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

Cela a fonctionné pour moi .. !!

Siva Kumar
la source
0

Si vous remarquez que vous devez revenir immédiatement après la fusion et que vous n'avez rien fait d'autre après la tentative de fusion, vous pouvez simplement émettre cette commande: git reset --hard HEAD@{1} .

Essentiellement, votre fusion shaindiquera HEAD@{0}si rien d'autre n'a été validé après la fusion et HEAD@{1}sera donc le point précédent avant la fusion.

Dut A.
la source
0

La plus simple des chances les plus simples, beaucoup plus simple que tout ce qui est dit ici:

Supprimez votre branche locale (locale, pas distante) et tirez-la à nouveau. De cette façon, vous annulerez les modifications sur votre branche principale et tout le monde sera affecté par le changement que vous ne voulez pas pousser. Recommencez.

Luis
la source
0

Dans ce cas, vous voudrez réinitialiser votre branche avec git reset --hard <branch_name>. Si vous souhaitez enregistrer vos modifications avant de les réinitialiser, assurez-vous de créer une nouvelle branche et git checkout <branch_name>.

Vous pouvez également réinitialiser l'état à un commit spécifique avec git reset --hard <commit_id>.

Si les modifications ont été poussées, vous pouvez les utiliser à la git revert <branch_name>place. Assurez-vous de vérifier comment utiliser git revert et git checkout dans d'autres scénarios également.

Nesha Zoric
la source