Pourquoi git revert se plaint-il d'une option -m manquante?

185

Je travaille donc sur un projet avec d'autres personnes, et plusieurs forks github sont en cours de travail. Quelqu'un vient de corriger un problème et j'ai fusionné avec son fork, mais j'ai réalisé que je pouvais trouver une meilleure solution. Je veux revenir sur le commit que je viens de faire. J'ai essayé de le faire avec git revert HEADmais cela m'a donné cette erreur:

fatal: Commit <SHA1> est une fusion mais aucune option -m n'a été donnée.

Qu'est-ce que ça veut dire? Quand j'ai fusionné et engagé, j'ai utilisé l'option -m pour dire "Fusionné avec <username>".

Qu'est-ce que je fais de mal ici?

icnhzabot
la source

Réponses:

217

Par défaut, git revertrefuse d'annuler une validation de fusion car ce que cela signifie réellement est ambigu. Je présume que vous êtes HEADen fait un commit de fusion.

Si vous voulez annuler la validation de la fusion, vous devez spécifier le parent de la fusion que vous voulez considérer comme le tronc principal, c'est-à-dire vers quoi vous voulez revenir.

Souvent, ce sera le parent numéro un, par exemple si vous étiez sur masteret l' avez fait git merge unwanted, puis avez décidé d'annuler la fusion de unwanted. Le premier parent serait votre masterbranche avant la fusion et le deuxième parent serait la pointe de unwanted.

Dans ce cas, vous pouvez faire:

git revert -m 1 HEAD
CB Bailey
la source
4
OK merci. J'ai trouvé plus facile de simplement modifier les deux fichiers affectés par la fusion, puis de valider certaines de mes autres modifications.
icnhzabot
43
Où puis-je trouver des informations si je dois utiliser -m1 ou -m2, ...?
Patrick Cornelissen
34
git cat-file -p [MERGE_COMMIT_ID]affichera les branches parentes dans l'ordre. Le premier listé serait -m 1, le second -m 2.
nostromo
2
git revert [HASH] -m 2me dit sur la branche 1.x-1.x rien à valider, le répertoire de travail est nettoyé mais mon commit n'est pas annulé.
jenlampton
3
Donc, si je dois revenir au-delà de 10 fusions (ce qui est très probable puisque git effectue une fusion automatiquement chaque fois que j'apporte des modifications d'un autre développeur), je dois le faire pour chaque fusion? Est-ce pour cela que les fans de git sont si désireux de rebaser, parce que le retour est fondamentalement inutile?
Neutrino du
46

Disons que l'autre gars a créé un bar au-dessus de foo, mais que vous avez créé baz entre-temps et que vous avez fusionné, donnant un historique de

$ git lola
* 2582152 (HEAD, master) Fusionner la branche 'otherguy'
| \  
| * barre c7256de (otherguy)
* | b7e7176 baz
| /  
* 9968f79 foo

Remarque: git lola est un alias non standard mais utile.

Pas de dés avec git revert:

$ git revert HEAD
fatal: Commit 2582152 ... est une fusion mais aucune option -m n'a été donnée.

Charles Bailey a donné une excellente réponse comme d'habitude. Utilisation git revertcomme dans

$ git revert --no-edit -m 1 HEAD
[master e900aad] Rétablir "Fusionner la branche 'otherguy'"
 0 fichiers modifiés, 0 insertions (+), 0 suppressions (-)
 mode suppression 100644 bar

supprime efficacement baret produit un historique de

$ git lola
* e900aad (HEAD, master) Revert "Fusionner la branche 'otherguy'"
* 2582152 Fusionner la branche 'otherguy'
| \  
| * barre c7256de (otherguy)
* | b7e7176 baz
| /  
* 9968f79 foo

Mais je soupçonne que vous voulez supprimer le commit de fusion:

$ git reset --hard HEAD ^
HEAD est maintenant chez b7e7176 baz

$ git lola
* b7e7176 (HEAD, maître) baz
| * barre c7256de (otherguy)
| /  
* 9968f79 foo

Comme documenté dans le git rev-parsemanuel

<rev>^, par exemple HEAD ^,v1.5.1^0
Un suffixe ^à un paramètre de révision signifie le premier parent de cet objet de validation. ^<n>signifie le n -ième parent ( c'est <rev>^ -à- dire équivaut à <rev>^1). En règle spéciale, <rev>^0signifie le commit lui-même et est utilisé quand <rev>est le nom d'objet d'un objet tag qui fait référence à un objet commit.

donc avant d'invoquer git reset, HEAD^(ou HEAD^1) était b7e7176 et HEAD^2c7256de, c'est -à- dire respectivement les premier et deuxième parents du commit de fusion.

Soyez prudent git reset --hardcar cela peut détruire le travail.

Greg Bacon
la source
3
C'est un monde confus, confus, bouleversé. Sauf pour Lola. Merci mille fois pour ce fantastique alias.
Barney
Un moyen simple d'ajouter lolaà vos commandes git:git config --global alias.lola "log --graph --decorate --pretty=oneline --abbrev-commit --all"
D. Gibbs
8

J'ai eu ce problème, la solution était de regarder le graphe de commit (en utilisant gitk) et de voir que j'avais ce qui suit:

*   commit I want to cherry-pick (x)
|\  
| * branch I want to cherry-pick to (y)
* | 
|/  
* common parent (x)

Je comprends maintenant que je veux faire

git cherry-pick -m 2 mycommitsha

C'est parce -m 1que fusionnerait en fonction du parent commun où, en tant que -m 2fusion en fonction de la branche y, c'est celle que je veux choisir.

shmish111
la source
1
Peut-être parce que ce n'est pas lié à git-revert, c'est le sujet de cette question.
pnomolos
1
Je pense que cette question concerne l' -moption, pas exclusivement git merge. C'est-à-dire que le raisonnement derrière l'utilisation de l' -moption semble être similaire pour les retours et les choix de cerises. Si ce n'est pas vrai, veuillez nous en informer. Comme je n'ai trouvé aucune autre question traitant spécifiquement de son utilisation sélective, merci pour cette réponse, qui a probablement conduit Google à m'aider à trouver cette question et une discussion utile et pertinente!
nealmcb