¿Por qué git revert se queja de que falta una opción -m?

185

Así que estoy trabajando en un proyecto con otras personas, y hay varios tenedores de github en los que se está trabajando. Alguien solucionó un problema y me fusioné con su tenedor, pero luego me di cuenta de que podía encontrar una mejor solución. Quiero revertir el compromiso que acabo de hacer. Intenté hacer esto con git revert HEADpero me dio este error:

fatal: Commit <SHA1> es una fusión pero no se dio la opción -m.

Qué significa eso? Cuando me fusioné y me comprometí, utilicé la opción -m para decir "Combinado con <nombre de usuario>".

¿Qué estoy haciendo mal aquí?

icnhzabot
fuente

Respuestas:

217

Por defecto, se git revertniega a revertir una confirmación de fusión, ya que lo que realmente significa es ambiguo. Supongo que su HEADes, de hecho, un compromiso de fusión.

Si desea revertir la confirmación de fusión, debe especificar a qué padre de la fusión desea considerar el enlace principal, es decir, a qué desea revertir.

A menudo, este será el padre número uno, por ejemplo, si estaba encendido mastery lo hizo git merge unwantedy luego decidió revertir la fusión de unwanted. El primer padre sería su masterrama previa a la fusión y el segundo padre sería la punta de unwanted.

En este caso podrías hacer:

git revert -m 1 HEAD
CB Bailey
fuente
44
OK gracias. Me resultó más fácil simplemente cambiar los dos archivos que se vieron afectados por la fusión y luego confirmar algunos de mis otros cambios también.
icnhzabot
43
¿Dónde puedo encontrar información si tengo que usar -m1 o -m2, ...?
Patrick Cornelissen
34
git cat-file -p [MERGE_COMMIT_ID]mostrará las ramas principales en orden. El primero en la lista sería -m 1, el segundo -m 2.
nostromo
2
git revert [HASH] -m 2me dice En la rama 1.x-1.x no hay nada que confirmar, el directorio de trabajo está limpio pero mi confirmación no se revierte.
jenlampton
3
Entonces, si necesito revertir más de 10 fusiones (lo cual es bastante probable ya que git realiza una fusión automáticamente cada vez que realizo cambios de otro desarrollador), ¿tengo que hacer esto para cada fusión? ¿Es por eso que los fanáticos de git están tan interesados ​​en rebase, porque revertir es básicamente inútil?
Neutrino
46

Digamos que el otro tipo creó una barra encima de foo, pero mientras tanto creaste baz y luego te uniste, dando un historial de

$ git lola
* 2582152 (HEAD, master) Fusionar rama 'otherguy'
| \  
El | * Barra c7256de (otro tipo)
* | b7e7176 baz
| /  
* 9968f79 foo

Nota: git lola es un alias no estándar pero útil.

Sin dados con git revert:

$ git revert HEAD
fatal: Commit 2582152 ... es una fusión, pero no se dio la opción -m.

Charles Bailey dio una excelente respuesta como siempre. Utilizando git revertcomo en

$ git revert --no-edit -m 1 HEAD
[master e900aad] Revertir "Fusionar rama 'otherguy'"
 0 archivos modificados, 0 inserciones (+), 0 eliminaciones (-)
 modo de eliminación 100644 bar

elimina bary produce efectivamente un historial de

$ git lola
* e900aad (HEAD, master) Revertir "Fusionar rama 'otherguy'"
* 2582152 Fusionar rama 'otherguy'
| \  
El | * Barra c7256de (otro tipo)
* | b7e7176 baz
| /  
* 9968f79 foo

Pero sospecho que quieres tirar el commit de fusión:

$ git reset --HAD HEAD ^
HEAD ahora está en b7e7176 baz

$ git lola
* b7e7176 (HEAD, master) baz
El | * Barra c7256de (otro tipo)
| /  
* 9968f79 foo

Como se documenta en el git rev-parsemanual

<rev>^, por ejemplo, HEAD ^,v1.5.1^0
un sufijo ^para un parámetro de revisión significa el primer padre de ese objeto de confirmación. ^<n>medios el n padre-ésimo ( es decir, <rev>^ es equivalente a <rev>^1). Como regla especial, <rev>^0significa el compromiso en sí y se usa cuando <rev>es el nombre del objeto de un objeto de etiqueta que se refiere a un objeto de compromiso.

así que antes de invocar git reset, HEAD^(o HEAD^1) era b7e7176 y HEAD^2era c7256de, es decir , respectivamente, el primer y el segundo padre de la confirmación de fusión.

Tenga cuidado git reset --hardporque puede destruir el trabajo.

Greg Bacon
fuente
3
Es un mundo confuso, confuso y sacudido. Excepto por Lola. Un millón de gracias por este fantástico alias.
Barney
Manera fácil de agregar lolaa sus comandos git:git config --global alias.lola "log --graph --decorate --pretty=oneline --abbrev-commit --all"
D. Gibbs
8

Tuve este problema, la solución fue mirar el gráfico de confirmación (usando gitk) y ver que tenía lo siguiente:

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

Ahora entiendo que quiero hacer

git cherry-pick -m 2 mycommitsha

Esto se debe a que -m 1se fusionaría en función del padre común, donde como se -m 2fusiona en función de la rama y, esa es la que quiero elegir.

shmish111
fuente
1
Posiblemente porque no está relacionado git-revert, de eso se trata esta pregunta.
pnomolos
1
Creo que esta pregunta es sobre la -mopción, no exclusivamente sobre git merge. Es decir, el razonamiento detrás del uso de la -mopción parece ser similar para reversiones y selecciones de cereza. Si eso no es cierto, háganoslo saber. Como no he encontrado ninguna otra pregunta que aborde específicamente su uso, gracias por esta respuesta, que probablemente llevó a google a ayudarme a encontrar esta pregunta y una discusión útil y relevante.
nealmcb