Revertir una fusión Git

225
develop branch
--> dashboard (working branch)

Utilizo git merge --no-ff developpara fusionar cualquier cambio aguas arriba en el tablero

registro de git:

commit 88113a64a21bf8a51409ee2a1321442fd08db705
Merge: 981bc20 888a557
Author: XXXX <>
Date:   Mon Jul 30 08:16:46 2012 -0500

    Merge branch 'develop' into dashboard

commit 888a5572428a372f15a52106b8d74ff910493f01
Author: root <[email protected]>
Date:   Sun Jul 29 10:49:21 2012 -0500

    fixed end date edit display to have leading 0

commit 167ad941726c876349bfa445873bdcd475eb8cd8
Author: XXXX <>
Date:   Sun Jul 29 09:13:24 2012 -0500

La fusión tenía más de 50 confirmaciones, y me pregunto cómo revertir la fusión para que el tablero vuelva al estado previo a la fusión.

La segunda parte de esto es, si no me fusiono --no-ff, no obtengo el compromiso ' Fusionar rama' desarrollar 'en el tablero '. ¿Cómo revertiría esa fusión?

cgmckeever
fuente
3
Posible duplicado de Undo a Git merge? .

Respuestas:

320

Revertir un compromiso de fusión se ha cubierto exhaustivamente en otras preguntas. Cuando realiza una combinación de avance rápido, la segunda que describe, puede usar git resetpara volver al estado anterior:

git reset --hard <commit_before_merge>

Puede encontrar el <commit_before_merge>con git reflog, git logo, si siente el moxy (y no ha hecho nada más):git reset --hard HEAD@{1}

Christopher
fuente
66
gracias por la respuesta rápida ... mirando git log, el commit antes de la fusión es de más de 50 commits, ya que el desarrollo de git merge realmente incluye todos los otros commits. Supongo que lo que no obtengo es, si no sé qué / dónde fue esa fusión, ¿cómo la encuentro? Usted menciona encontrar el commit_before_merge .. Supongo que no entiendo esa parte
cgmckeever
44
parece que con git reflog parece que resume muy bien las últimas cabezas y me permite saber dónde debo reiniciar. git log parece tener demasiada granularidad para identificar el lugar al que restablecer. Gracias
cgmckeever
1
Sí, refloges un salvavidas. HEAD@{1}simplemente describe el segundo estado más reciente de HEAD, o más técnicamente: "Una referencia seguida del sufijo @ con una especificación ordinal encerrada en un par de llaves (por ejemplo, {1}, {15}) especifica el enésimo valor anterior de ese árbitro."
Christopher
44
¿Qué hay de empujar la reversión a control remoto? No veo cómo funcionará.
Anton Savelyev
2
Esto no tiene remedio. Destruye todos los commits después de la fusión.
aaa90210
151

De aquí:

http://www.christianengvall.se/undo-pushed-merge-git/

git revert -m 1 <merge commit hash>

Git revert agrega una nueva confirmación que revierte la confirmación especificada.

El uso de -m 1 le dice que se trata de una fusión y que queremos retroceder a la confirmación principal en la rama maestra. Usaría -m 2 para especificar la rama de desarrollo.

Sturrockad
fuente
30
Tenga en cuenta que no puede volver a fusionar la rama después de esto, como dice la documentación: "Revertir una confirmación de fusión declara que nunca querrá que los cambios de árbol sean traídos por la fusión. Como resultado, las fusiones posteriores solo traerán cambios de árbol introducidos por commits que no son ancestros de la fusión revertida anteriormente. Esto puede o no ser lo que quieres ".
Dalibor Karlović
23
@ DaliborKarlović Esa declaración es un poco dura. Definitivamente puede recuperar esos cambios más tarde, el truco es revertir la confirmación de reversión. Más información aquí en la sección "Revertir la reversión"
Hilikus
3
Lamentablemente, el hereenlace en el comentario @Hilikus ya no es válido. El sitio afirma que el contenido se movió a un libro ( git-scm.com/book/en/v2 ), pero si es así, no es trivial ubicarlo allí.
Jesse Chisholm
@ DaliborKarlović ¿es este el caso con la respuesta anterior de @ Christopher?
James B
3
El contenido de deshacer fusiones se trasladó a aquí
SEK
28

Simplemente restablezca la confirmación de fusión con git reset --hard HEAD^.

Si usa --no-ff git siempre crea una fusión, incluso si no confirmó nada en el medio. Sin --no-ff git solo hará un avance rápido, lo que significa que las ramas HEAD se establecerán en HEAD de la rama fusionada. Para resolver esto, busque el commit-id al que desea volver y git reset --hard $COMMITID.

Nico Erfurth
fuente
1
Buena solución si no conoce el commit antes de la fusión.
iglesiasedd
Trabajó para mí porque no sé commit id. + 1
Anant Singh --- Alive to Die
Si la fusión no deseada ya estaba comprometida con remoto, usé git push -f para actualizar la rama remota después de revertir.
zumek
16
git revert -m 1 88113a64a21bf8a51409ee2a1321442fd08db705

Pero puede tener efectos secundarios inesperados. Ver --mainline parent-numberopción en git-scm.com/docs/git-revert

Quizás una forma bruta pero efectiva sería revisar el padre izquierdo de ese commit, hacer una copia de todos los archivos, HEADvolver a pagar y reemplazar todo el contenido con los archivos antiguos. ¡Entonces git te dirá lo que se revierte y crearás tu propio compromiso de reversión :)!

Jorge Orpinel
fuente
1
+1 porque esta respuesta no se mete con el historial como lo hace el reinicio (realmente importante si ya presionó al control remoto). Pero, ¿qué efectos secundarios inesperados debo esperar?
pedromanoel
3
¿Es este el efecto secundario que mencionaste? Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want.
pedromanoel
1
Usted dice que git resetes la solución, pero también menciona que podría tener efectos secundarios inesperados. Sin embargo, ese enlace es de git revert, no git reset:)
Mark
2
Tenga en cuenta que git reset no tiene una marca -m. También tenga en cuenta @JorgeOrpinel hace referencia a los documentos git-revert, no a git-reset. Creo que quiso decir que git revertnogit reset
Devin Gleason Lambert
Se especificó cómo evitar Mainline pero commit 1234xyz no es un error de fusión .
Achal
0

Si fusionó la rama, revirtió la combinación utilizando una solicitud de extracción y fusionó esa solicitud de extracción para revertir.

La forma más fácil que sentí fue:

  1. Saque una nueva sucursal de desarrollo / maestro (donde se fusionó)
  2. Revierta el "revertir" usando git revert -m 1 xxxxxx(si la reversión se fusionó usando una rama) o usando git revert xxxxxxsi fue una simple reversión
  3. La nueva rama ahora debe tener los cambios que desea fusionar nuevamente.
  4. Hacer cambios o fusionar esta rama para desarrollar / dominar
Rohin Tak
fuente