Deshacer una confirmación particular en Git que se ha enviado a repositorios remotos

789

¿Cuál es la forma más sencilla de deshacer una confirmación particular que es:

  • no en la cabeza o CABEZA
  • Ha sido empujado al control remoto.

Porque si no es el último commit,

git reset HEAD

no funciona Y porque ha sido empujado a un control remoto,

git rebase -i

y

git rebase --onto

causará algún problema en los controles remotos.

Más aún, no quiero modificar la historia realmente. Si había un código incorrecto, estaba allí en la historia y se puede ver. Solo lo quiero en la copia de trabajo, y no me importa una confirmación de fusión inversa.

En otras palabras, ¿cuál es el equivalente Git de los siguientes comandos svn:

svn merge -r 303:295 http://svn.example.com/repos/calc/trunk

que elimina todos los cambios de 295 a 302 mediante la fusión inversa de todos los cambios en esas revisiones, como una nueva confirmación.

svn merge -c -302 ^/trunk

que deshace la confirmación 302, por supuesto, agregando otra confirmación que invierte combina los cambios de esa confirmación respectiva.

Pensé que debería ser una operación bastante simple en Git y un caso de uso bastante común. ¿Cuál es el objetivo de los compromisos atómicos?

Tenemos almacenamiento oculto y todo para garantizar que los commits sean perfectamente atómicos, ¿no debería poder deshacer uno o más de esos commits atómicos fácilmente?

Lakshman Prasad
fuente

Respuestas:

1211

Identifique el hash de la confirmación, usando git log, luego use git revert <commit>para crear una nueva confirmación que elimine estos cambios. En cierto modo, git revertes lo contrario de esto git cherry-pick: este último aplica el parche a una rama que le falta, el primero lo elimina de una rama que lo tiene.

Andrew Aylett
fuente
237
Y use el modificador -n si desea que se le devuelva el código, pero no se
confirme
17
¿Qué hace la opción "m"? Intenté git revert 8213f7d pero obtuve esto en su lugar: error: Commit 8213f7dad1ed546b434a0d8a64cb783b530a5a30 es una fusión pero no se dio la opción -m. fatal: error de reversión
Malcolm
10
Para revertir una fusión: git revert -m 1 <hash>
brunozrk
31
Una advertencia para cualquier persona que quiera revertir una fusión: git revert deshacerá todos los cambios de datos (es decir, los cambios del archivo se revertirán), pero la fusión aún permanece en el historial. Debido a esto, si intenta fusionar esa misma rama nuevamente más tarde, no incluirá ninguna confirmación de la rama de fusión antes de la fusión revertida. Es muy probable que esto no sea lo que quieres. Para volver a fusionar completamente la rama, primero deberá revertir la confirmación donde revirtió la fusión original. Obtenga más información aquí: kernel.mirrors.pair.com/pub/software/scm/git/docs/howto/…
etreworgy
3
El enlace en el comentario de @etreworgy es 404. Sospecho que esta es una versión actualizada del enlace: kernel.org/pub/software/scm/git/docs/howto/…
Tim Smith
368

No me gusta el autocomprometido que git revertsí, así que esto podría ser útil para algunos.

Si solo desea que los archivos modificados no sean la confirmación automática , puede usar--no-commit

% git revert --no-commit <commit hash>

que es lo mismo que el -n

% git revert -n <commit hash>
Gracias
fuente
99
También podría hacerlo git reset HEAD~1 --softsi ya revierte sin-n
Daniel
1
Pero git reset HEAD~nno resolverá la eliminación de ninguna confirmación que no sea accesible continuamente desde la cabeza. La consulta es revertir cualquier confirmación particular.
sangeethkumarp
Usé esta solución pero encontré un conflicto en medio de la reversión. Después de resolver el conflicto, hice lo git revert --continueque me indicó. Funcionó, pero lamentablemente comprometió los resultados. Tal vez necesitaba hacer git revert --no-commit --continue.
mareoraft
1
@sangeethkumarp el comentario de Daniel es un paso adicional que puede seguir después de git revert, si olvidó el -n; porque en ese punto la última confirmación es la reversión, por lo que el restablecimiento parcial deshacerá esa confirmación pero no los cambios de código asociados de la reversión
Oliver
@Daniel proporcionó soluciones por comentario, trabaje para mí Muchas gracias '' git reset HEAD ~ 1 --soft ''
Md. Abu Sayed
41

Debido a que ya se ha presionado, no debes manipular directamente el historial. git revertrevertirá cambios específicos de un commit usando un nuevo commit, para no manipular el historial de commit.

foso Pilón
fuente
1

Si el envío que desea revertir es un fusionaron comprometerse (ya se ha fusionado), entonces usted debe ya sea -m 1o -m 2opción como se muestra a continuación. Esto le permitirá a git saber qué commit primario del commit combinado para usar. Más detalles se pueden encontrar AQUÍ .

  • git revert <commit> -m 1
  • git revert <commit> -m 2
Meysam Sadeghi
fuente