web-dev-qa-db-fra.com

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

Dans ma branche principale, j’ai effectué un git merge some-other-branch localement, mais n’ai jamais transmis les modifications à Origin Master. Je ne voulais pas fusionner, alors j'aimerais le défaire. Lorsque je faisais un git status après ma fusion, je recevais ce message:

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

Basé sur quelques instructions que j'ai trouvées , j'ai essayé de courir

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?

3349
Matt Huggins

Avec git reflog, vérifiez quelle validation est antérieure à la fusion (git reflog sera une meilleure option que git log). Ensuite, vous pouvez le réinitialiser en utilisant:

git reset --hard commit_sha

Il y a aussi un autre moyen:

git reset --hard HEAD~1

Cela vous ramènera 1 commit.

Sachez que tous les fichiers modifiés et non validés/non stockés seront réinitialisés à leur état non modifié . Pour les conserver, stockez les modifications ou consultez l’option --merge ci-dessous. 


Comme @Velmont a suggéré ci-dessous dans sa réponse, dans ce cas direct en utilisant:

git reset --hard ORIG_HEAD

pourrait donner de meilleurs résultats, car il devrait préserver vos modifications. ORIG_HEAD pointe vers un commit directement avant la fusion, vous n'avez donc pas à le rechercher vous-même.


Une autre astuce consiste à utiliser le commutateur --merge au lieu de --hard car 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'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 non ajoutées). 

3709
Marcin Gil

En supposant que votre maître local n’ait pas devancé l’origine/maître, vous devriez pouvoir faire

git reset --hard Origin/master

Ensuite, votre branche master locale doit être identique à Origin/master.

1335
randomguy3

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

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

git revert -m 1 commit_hash

Assurez-vous de revenir en arrière si vous réengagez la branche, comme l'a dit Linus.

1109
Yuri Geinish

Il est étrange que la commande la plus simple fût absente. La plupart des réponses fonctionnent, mais annulent la fusion que vous venez de faire, c’est un moyen simple et sûr :

git reset --merge ORIG_HEAD

La ref ORIG_HEAD pointera vers le commit d'origine d'avant la fusion.

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

897
odinho - Velmont

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é que lorsque la fusion a abouti à des conflits. git merge --abort annulera le processus de fusion et tentera de reconstruire l'état de pré-fusion.

342
Travis Reeder

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

git reset --hard HEAD^

Ou même HEAD^^ pour annuler cette annulation de validation. Vous pouvez toujours donner une référence complète SHA si vous n’êtes pas sûr du nombre de pas à faire en arrière.

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

117
MBO

Dernièrement, j'ai utilisé git reflog pour aider avec ceci. Cela ne fonctionne généralement que si la fusion JUST a eu lieu et qu'elle se trouvait sur votre machine. 

git reflog peut retourner 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 a eu lieu. La 2ème ligne est le temps avant ma fusion. Je simplement git reset --hard 43b6032 pour forcer cette branche à effectuer un suivi avant la fusion et à continuer.

81
Parris

Avec Git moderne, vous pouvez:

git merge --abort

Ancienne syntaxe:

git reset --merge

Vieille école:

git reset --hard

Mais en réalité, il convient de noter que git merge --abort n’est équivalent qu’à git reset --merge étant donné que MERGE_HEAD est présent. 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 une fusion manquée, quand il n'y a pas de MERGE_HEAD, celle-ci peut être annulée avec git reset --merge, mais pas nécessairement avec git merge --abort, afin qu'elles ne constituent pas seulement l'ancienne et la 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.

48
Martin G

D'accord, les réponses que d'autres personnes m'ont données ici é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û saisir la même commande git reset plusieurs fois. Chaque fois que je faisais cela, le message était modifié de une fois, 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é, alors j'ai essayé de faire un git pull, et cela a semblé 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

Si longue histoire, mes commandes se résument à ceci:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull
36
Matt Huggins

Vous pouvez utiliser git reflog pour trouver la dernière transaction. Parfois, c'est un bon état dans lequel vous souhaitez revenir.

Concrètement

$ git reflog
$ git reset --hard HEAD@{0}
21
stephjang

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

$ git checkout -f

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

13
Idealmind

Nous sommes arrivés à cette question qui cherche également à revenir à l'origine (c.-à-d. Que NO s'engage avant l'origine). En cherchant plus loin, nous avons trouvé une commande reset pour exactement 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.)

12
leanne

Juste pour une option supplémentaire à regarder, je suivais principalement le modèle de branchement décrit ici: http://nvie.com/posts/a-susuccessful-git-branching-model/ et en tant que tels ont été fusion avec --no-ff (pas d'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 version avec master pour le déploiement (site Web, maître est ce qui est en direct). La branche testing regroupe deux autres branches et totalise environ six commits. 

Donc, pour annuler le commit complet, il me fallait juste un git reset --hard HEAD^ et la reprise complète. Comme les fusions n'ont pas été transférées rapidement, la fusion était un bloc et un pas en arrière est "branche non fusionnée".

10
Damien Byrne

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

  1. git reset --hard commitHash (vous devez utiliser le commit que vous voulez 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!

10
Matheus Abreu

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 une fois les modifications apportées, faites ceci .__ (car il s’agit du premier message affiché pour les questions relatives à la réinitialisation de git)

git Push Origin HEAD --force

Cela réinitialisera de manière à ne pas récupérer les modifications fusionnées après l'extraction.

8
Harsha

Si votre fusion et les commits correspondants n'ont pas encore été envoyés, vous pouvez toujours basculer vers une autre branche, supprimer celle d'origine et la recréer.

Par exemple, j'ai accidentellement fusionné une branche de développement avec le maître et je voulais 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 Origin et votre état de fusion erroné est effacé.

7
Stephan

J'ai pu résoudre ce problème avec une seule commande qui n'implique pas la recherche d'un identifiant de validation.

git reset --hard remotes/Origin/HEAD

La réponse acceptée ne fonctionnait pas pour moi, mais cette commande donnait les résultats que je recherchais.

6
Ralph Ritoch

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

Si vous êtes un débutant, vous pourriez aimer l’approche graphique:

  1. Lancez gitk (à partir de la ligne de commande, ou cliquez avec le bouton droit dans le navigateur de fichiers si vous en avez)
  2. Vous pouvez facilement repérer le commit de fusion là - le premier nœud du haut avec deux parents
  3. Suivez le lien vers le premier/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 de la souris sur "Réinitialiser la branche ici", sélectionnez la réinitialisation matérielle à cet emplacement.
4
inger

Stratégie: / Créer une nouvelle branche à partir de laquelle tout allait bien.

Justification: Inverser une fusion est difficile. Il y a trop de solutions, en fonction de nombreux facteurs, tels que le fait que vous ayez commis ou que vous ayez poussé votre fusion ou qu'il y ait eu de nouveaux commits depuis votre fusion. En outre, vous devez toujours avoir une compréhension assez approfondie de git pour adapter ces solutions à votre cas. Si vous suivez aveuglément certaines instructions, vous pouvez vous retrouver avec une "fusion à vide" dans laquelle rien ne sera fusionné. De nouvelles tentatives de fusion permettront à Git de vous dire "Déjà à jour".

Solution:

Supposons que vous souhaitiez fusionner dev dans feature-1.

  1. Recherchez la révision pour laquelle 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 (retournez dans le temps):

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

    git checkout -b feature-1
    

Maintenant, vous pouvez redémarrer votre fusion:

  1. Fusionner: git merge dev

  2. Corrigez vos conflits de fusion.

  3. Valider: git commit

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

4
pyb

Vous devez changer votre tête, pas à vous bien sûr mais git HEAD ....

Donc, avant de répondre, ajoutons un peu d’arrière-plan et expliquons ce qu’est cette HEAD.

First of all what is HEAD?

HEAD est simplement une référence à la validation actuelle (la plus récente) de la branche actuelle.
Il ne peut y avoir qu’un seul HEAD à un moment donné. (excluant _git worktree_)

Le contenu de HEAD est stocké dans _.git/HEAD_ et contient les 40 octets SHA-1 de la validation actuelle.


detached HEAD

Si vous n'êtes pas sur la dernière validation - ce qui signifie que HEAD pointe sur une validation précédente de l'historique, elle est appelée detached HEAD.

enter image description here

Sur la ligne de commande, cela ressemblera à ceci: SHA-1 au lieu du nom de la branche, car la HEAD ne pointe pas vers la pointe de la branche en cours.

enter image description here

enter image description here

Quelques options sur la façon de récupérer d'une tête isolé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 vérifier la nouvelle branche pointant vers le commit désiré.
Cette commande passera à un commit donné.
À ce stade, vous pouvez créer une branche et commencer à travailler à partir de ce moment.

_# 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 toujours utiliser le reflog.
_git reflog_ affichera tout changement mettant à jour le HEAD et extraire l'entrée de reflog désirée ramènera le HEAD à ce commit.

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

_git reflog
git checkout HEAD@{...}
_

Cela vous ramènera à votre commit désiré

enter image description here


git reset --hard <commit_id>

"Déplacez 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.
_
  • Note: ( 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 à la validation donnée.
Un nouveau commit avec le correctif 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 && checkout_ modifie la HEAD.

enter image description here

3
CodeWizard

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

2
llioor

Je pense que vous pouvez faire git rebase -i [hash] [branch_name][hash] est le hachage d'identification, quelle que soit la date à laquelle vous souhaitez revenir en arrière plus un (ou le nombre de commits que vous souhaitez supprimer), puis supprimer les lignes que vous ne souhaitez pas dans l'éditeur pas 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 commits 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 souhaitez probablement pas.

1
tychoish

Si vous avez commis la fusion:

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

  2. Puis réinitialisez votre référentiel à l'état de fonctionnement précédent:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

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

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

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

  3. Cochez les commits 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 engagements sur 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 choisissant une gamme de commits en:

      • Commencez par vérifier les bons changements avant de les fusionner:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • Commencez par vérifier les bons changements avant de les fusionner:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        où il s'agit de la plage des commits corrects que vous avez commis (à l'exclusion de la fusion mal engagée).

1
kenorb

Cela peut être fait de plusieurs manières.

1) Abort Merge

Si vous êtes entre deux mauvaises fusions (faites par erreur avec une mauvaise branche), et que vous voulez éviter la fusion, vous devez revenir à la dernière branche comme ci-dessous:

git merge --abort

2) réinitialiser HEAD dans la branche distante

Si vous travaillez depuis une branche de développement distante, vous pouvez réinitialiser HEAD au dernier commit sur la branche distante, comme indiqué ci-dessous:

git reset --hard Origin/develop

) Supprimez la branche actuelle et extrayez-la à nouveau du référentiel distant

Considérant que vous travaillez sur la branche de développement dans le référentiel local, qui se synchronise avec la branche à distance/de développement, vous pouvez procéder comme suit:

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
1
Anamika

Le plus simple des plus simples hasard, beaucoup plus simple que tout ce qui est dit ici:

Supprimez votre branche locale (locale, non distante) et tirez-la à nouveau. De cette façon, vous annulerez les modifications apportées à votre branche principale et les modifications que vous ne souhaitez pas transférer affecteront tout le monde. Recommencez.

0
Luis
  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 .. !!

0
Siva Kumar

Il suffit de créer une nouvelle branche, puis de sélectionner les modifications souhaitées.

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

0
devi

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

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

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

0
Nesha Zoric

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 exécuter cette commande: git reset --hard HEAD@{1}.

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

0
Dut A.