J'ai rencontré un conflit de fusion. Comment annuler la fusion?

2539

J'ai utilisé git pullet j'ai eu un conflit de fusion:

unmerged:   _widget.html.erb

You are in the middle of a conflicted merge.

Je sais que l'autre version du fichier est bonne et que la mienne est mauvaise, donc toutes mes modifications doivent être abandonnées. Comment puis-je faire ceci?

Gwyn Morfey
la source
30
Je me rends compte que c'est une très vieille question, mais voulez-vous abandonner la fusion entière et laisser la branche que vous fusionniez non fusionnée, ou ignorer simplement ce fichier dans le cadre d'une fusion plus large, laissant tous les autres fichiers fusionner en tant que Ordinaire? Pour moi, votre titre implique le premier, votre corps de question veut le second. Les réponses font les deux, sans clarifier les choses.
rjmunro
J'ai reçu un cas similaire lors de la validation disant que la fusion automatique a échoué; résoudre les conflits et ensuite valider le résultat:[rejected] gh-pages -> gh-pages (non-fast-forward)
Chetabahana
4
Gwyn, il pourrait être utile de sélectionner une réponse acceptée ici. La solution la plus votée est un peu moins sûre que certaines des solutions les plus récentes, donc je pense que cela aiderait à en mettre d'autres en évidence :)
Amical

Réponses:

2222

Étant donné que votre pulléchec a été HEAD(pas HEAD^) le dernier commit "valide" sur votre branche:

git reset --hard HEAD

L'autre élément que vous souhaitez est de laisser leurs modifications l'emporter sur vos modifications.

Les versions plus anciennes de git vous permettaient d'utiliser la stratégie de fusion "leur":

git pull --strategy=theirs remote_branch

Mais cela a depuis été supprimé, comme expliqué dans ce message par Junio ​​Hamano (le responsable de Git). Comme indiqué dans le lien , vous feriez plutôt ceci:

git fetch origin
git reset --hard origin
Pat Notz
la source
49
Au lieu de faire une réinitialisation matérielle, vous pouvez l'amener à un niveau plus granulaire en faisant: git fetch origin -> git reset origin (soft reset, your changes are still present) -> git checkout file_to_use_their_version_of another_file (steamroll your own changes back to match the origin) Je n'utilise plus git pull. Puisque dans un combat entre mon dernier code et l'origine, l'origine devrait toujours gagner, moi toujours git fetchet git rebase origin. Cela rend en fait mes fusions et mes conflits rares.
Kzqai
7
Je suis d'accord. J'aime aussi aller chercher d'abord, puis examiner les changements en amont ( git log ..@{upstream}ou git diff ..@{upstream}). Après ça, comme vous, je vais rebaser mon travail.
Pat Notz
162
Comme indiqué dans une réponse plus récente, à partir de la version 1.6.1, il est possible d'utiliser 'git reset --merge'
Matt Ball
5
J'ai utilisé git merge -X theirs remote_branchau lieu de git pull --strategy=theirs remote_branchcomme theirsressemble à une option derecursive
mlt
14
git merge --abortest de loin préférable.
Daniel Cassidy
1956

Si votre version git est> = 1.6.1, vous pouvez utiliser git reset --merge.

De plus, comme @Michael Johnson le mentionne, si votre version git est> = 1.7.4, vous pouvez également utiliser git merge --abort.

Comme toujours, assurez-vous de n'avoir aucune modification non validée avant de démarrer une fusion.

Depuis la page de manuel de git merge

git merge --abort est équivalent à git reset --merge quand MERGE_HEADest présent.

MERGE_HEAD est présent lorsqu'une fusion est en cours.

En outre, concernant les modifications non validées lors du démarrage d'une fusion:

Si vous avez des modifications que vous ne souhaitez pas valider avant de commencer une fusion, juste git stashavant la fusion et git stash popaprès avoir terminé ou abandonné la fusion.

Carl
la source
3
Intéressant - mais le manuel me fait peur. Quand est-il approprié d'utiliser? Quand devrez-vous spécifier l'option <commit>? #GitMoment: -o
conny
1
Vous l'utiliseriez généralement lorsque vous souhaitez refaire la fusion depuis le début. Je n'ai jamais eu à spécifier le commit optionnel moi-même, donc la valeur par défaut (pas de <commit> optionnel) est très bien.
Carl
44
Je souhaite que cette réponse ait plus de votes! À ce stade, cela semble être la solution la plus pertinente dans de nombreux cas.
Jay Taylor
1
Même avec des modifications non validées, git a pu restaurer l'état avant la fusion. Agréable!
T3rm1
2
Est-ce git merge --abortjuste un synonyme de git reset --merge? Le nom a certainement plus de sens, mais a-t-il la même fonctionnalité?
Tikhon Jelvis
518
git merge --abort

Abandonnez le processus de résolution de conflit actuel et essayez de reconstruire l'état de pré-fusion.

S'il y avait des modifications non validées de la zone de travail au début de la fusion, il git merge --abortsera dans certains cas impossible de reconstruire ces modifications. Il est donc recommandé de toujours valider ou cacher vos modifications avant d'exécuter git merge.

git merge --abortéquivaut à git reset --mergequand MERGE_HEADest présent.

http://www.git-scm.com/docs/git-merge

ignis
la source
16
Ceci est disponible depuis git v1.7.4. C'est un alias pour git reset --merge.
Michael Johnson
162

C'est tellement simple.

git merge --abort

Git lui-même vous montre la solution lorsque vous rencontrez ce type de problème et exécutez la commande git status.

git status

J'espère que cela aidera les gens.

Jagruttam Panchal
la source
97

Je pense que c'est git resetce dont vous avez besoin.

Attention, cela git revertsignifie quelque chose de très différent de, disons, svn revert- dans Subversion, le retour annulera vos modifications (non validées), en renvoyant le fichier à la version actuelle depuis le référentiel, tandis que git revert"annule" un commit.

git resetdevrait faire l'équivalent de svn revert, c'est-à-dire rejeter vos modifications indésirables.

David Precious
la source
76

Dans ce cas d'utilisation particulier, vous ne voulez pas vraiment abandonner la fusion, mais simplement résoudre le conflit d'une manière particulière.

Il n'est pas non plus nécessaire de réinitialiser et d'effectuer une fusion avec une stratégie différente. Les conflits ont été correctement mis en évidence par git et l'exigence d'accepter les modifications des autres côtés ne concerne que ce fichier.

Pour un fichier non fusionné dans un conflit, git met à disposition les versions de base commune, locale et distante du fichier dans l'index. (C'est là qu'ils sont lus pour être utilisés dans un outil de différenciation à 3 voies par git mergetool.) Vous pouvez les utiliser git showpour les visualiser.

# common base:
git show :1:_widget.html.erb

# 'ours'
git show :2:_widget.html.erb

# 'theirs'
git show :3:_widget.html.erb

La manière la plus simple de résoudre le conflit pour utiliser la version distante textuellement est:

git show :3:_widget.html.erb >_widget.html.erb
git add _widget.html.erb

Ou, avec git> = 1.6.1:

git checkout --theirs _widget.html.erb
CB Bailey
la source
5
merci pour l'astuce. n'est-ce pas une mauvaise interface utilisateur git, cependant?
Peter
@Peter: Je ne suis pas convaincu. Le résultat souhaité est réalisable avec quelques commandes de base avec des options simples. Quelles améliorations suggéreriez-vous?
CB Bailey
10
Je pense que la git 1.6.1commande a beaucoup de sens et est bonne. C'est exactement ce que j'aurais voulu. Je pense que la solution pré-1.6.1 est inélégante et nécessite des connaissances sur d'autres parties de git qui devraient être séparées du processus de résolution de fusion. Mais la nouvelle version est géniale!
Peter
67

Pour le scénario comme je l'ai fait git fetchet git pull, puis se rendit compte que la branche amont n'a pas été branche principale, ce qui a donné lieu à des conflits indésirables.

git reset --merge 

Cela est revenu en arrière sans réinitialiser mes modifications locales.

naamadheya
la source
45

Les commentaires suggèrent qu'il git reset --merges'agit d'un alias pour git merge --abort. Il convient de noter que cela git merge --abortn'est équivalent qu'à git reset --mergeétant donné que a MERGE_HEADest présent. Cela peut être lu dans la commande git help for merge.

git merge --abort est équivalent à git reset --merge lorsque MERGE_HEAD est présent.

Après une fusion qui a échoué, quand il n'y en 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. Ce ne sont pas seulement d'anciennes et de nouvelles syntaxes pour la même chose .

Personnellement, je trouve git reset --mergebeaucoup plus puissant pour des scénarios similaires à celui décrit, et les fusions échouées en général.

Martin G
la source
2
qu'entend-on ici par «fusion ratée»? Fusionner avec des conflits ou autre chose? Ou pour le reformuler: quand MERGE_HEAD n'est pas présent? Ma question de suivi est là pour comprendre une meilleure utilisation de "git reset --merge".
Ewoks
@Ewoks a git stash applyprovoqué un conflit de fusion pour moi mais git merge --abortn'a pas aidé pendant git reset --mergece temps.
nitzel
27

Si vous vous retrouvez avec un conflit de fusion et que vous n'avez rien à valider, mais une erreur de fusion s'affiche toujours. Après avoir appliqué toutes les commandes mentionnées ci-dessous,

git reset --hard HEAD
git pull --strategy=theirs remote_branch
git fetch origin
git reset --hard origin

S'il vous plaît retirer

.git \ index.lock

Fichier [couper coller à un autre emplacement en cas de récupération], puis entrez l'une des commandes ci-dessous selon la version que vous souhaitez.

git reset --hard HEAD
git reset --hard origin

J'espère que cela pourra aider!!!

Nirav Mehta
la source
19

Une alternative, qui préserve l'état de la copie de travail, est:

git stash
git merge --abort
git stash pop

Je déconseille généralement cela, car cela revient à fusionner dans Subversion car il supprime les relations de branche dans le commit suivant.

Alain O'Dea
la source
J'ai trouvé cette approche utile lorsque j'ai fusionné accidentellement avec une branche git-svn, qui ne gère pas bien cela. Les fusions de squash ou les cerises sont meilleures lorsque vous travaillez avec des branches de suivi git-svn. En fait, ma solution transforme une fusion en fusion de squash après coup.
Alain O'Dea
Meilleure réponse à la question
Fouad Boukredine
18

Depuis Git 1.6.1.3 git checkouta été en mesure de passer à la caisse de chaque côté d'une fusion:

git checkout --theirs _widget.html.erb
Alain O'Dea
la source
3

J'ai trouvé que ce qui suit fonctionnait pour moi (rétablir un seul fichier à l'état de pré-fusion):

git reset *currentBranchIntoWhichYouMerged* -- *fileToBeReset*
Malcolm Boekhoff
la source
-5

Sourcetree

Parce que vous ne validez pas votre fusion, il vous suffit de double-cliquer sur une autre branche (ce qui signifie la vérifier) ​​et lorsque sourcetree vous demande de rejeter toutes les modifications, alors acceptez :)

Kamil Kiełczewski
la source