¿Cómo puedo deshacer un `git commit` localmente y en un control remoto después de` git push`

242

He realizado git commitseguido de a git push. ¿Cómo puedo revertir ese cambio en los repositorios locales y remotos?

$ git log
commit 364705c23011b0fc6a7ca2d80c86cef4a7c4db7ac8
Author: Michael Silver <Michael [email protected]>
Date:   Tue Jun 11 12:24:23 2011 -0700
Miguel
fuente

Respuestas:

400
git reset --hard HEAD~1
git push -f <remote> <branch>

(Ejemplo empuje: git push -f origin bugfix/bug123)

Esto deshacerá la última confirmación y empujará el historial actualizado al control remoto. Debe pasar el -fporque está reemplazando el historial ascendente en el control remoto.

Alexander Groß
fuente
24
Alternativamente, use git reset --hard <the-sha-you-want-to-return-to>.
Alexander Groß
2
La referencia se llama HEAD (distingue entre mayúsculas y minúsculas)
dunni
26
Además, tenga cuidado: AFAIK no debería estar haciendo esto si otras personas se han retirado del repositorio.
Amadan
1
@BipinVayalu Afecta la rama en la que estás actualmente. Más precisamente, la CABEZA. El HEAD se suele "adjuntar" a una rama (apuntando al nombre de una rama en lugar de señalar directamente a una confirmación). Entonces, en términos generales, afectará la rama a la que apunta HEAD. Úselo git log --decorate --onelinepara averiguar a dónde apunta su CABEZA.
Alexander Groß
44
git reset HEAD~1si no desea que se vayan sus cambios (cambios no organizados). Cambiar, comprometerse y presionar de nuevogit push -f [origin] [branch]
softvar
161

En general, realice una confirmación "inversa", utilizando:

git revert 364705c

luego envíelo al control remoto como de costumbre:

git push

Esto no eliminará la confirmación: realiza una confirmación adicional que deshace lo que hizo la primera confirmación. Cualquier otra cosa, no es realmente segura, especialmente cuando los cambios ya se han propagado.

Amadan
fuente
99
Esta es una respuesta más segura (por lo tanto, probablemente mejor) que la de Alexander Groß (la respuesta elegida).
Graeck
66
@Graeck Cada una de las soluciones tiene sus implicaciones y méritos.
Alexander Groß
55
Esta debería ser la respuesta aceptada, es una buena práctica nunca sobrescribir el historial, incluso más si colaboras con un equipo. git resetsolo se acepta si aún no ha enviado los cambios al servidor.
Josue Alexander Ibarra
17
@JosueIbarra No estoy de acuerdo con todos los casos. Para la mayoría de los casos, sí, no debe sobrescribir el historial. Sin embargo, creo que hay casos legítimos en los que absolutamente deberías. Por ejemplo, accidentalmente comete y empuja hacia arriba su archivo de secretos. Eso no debería estar en el repositorio de git. Por lo tanto, puede eliminarlo rápidamente utilizando la respuesta aceptada aquí.
bfcoder
11
@bfcoder si introdujo un "secreto" en un repositorio remoto, ya no es un secreto. Y la solución adecuada es crear un nuevo secreto, no tratar de ocultar su error.
erbsman
41

En primer lugar, relájate.

"Nada está bajo nuestro control. Nuestro control es mera ilusión", "Errar es humano"

Entiendo que involuntariamente presionaste tu código remote-master. ESTO va a estar bien.

1. Al principio, obtenga el SHA-1valor de la confirmación que está intentando devolver, por ejemplo, comprometerse con la rama maestra. ejecuta esto:

git log

verá un montón de 'f650a9e398ad9ca606b25513bd4af9fe ...' como cadenas junto con cada una de las confirmaciones. copie ese número de la confirmación que desea devolver .

2. Ahora, escriba el siguiente comando:

git reset --hard your_that_copied_string_but_without_quote_mark

debería ver un mensaje como "HEAD is now at". Estás en claro. Lo que acaba de hacer es reflejar ese cambio localmente.

3. Ahora, escriba el siguiente comando:

git push -f

deberías ver como

"advertencia: push.default no está establecido; su valor implícito ha cambiado en ..... ... Total 0 (delta 0), reutilizado 0 (delta 0) ... ... your_branch_name -> master (actualización forzada) ".

Ahora, ya está todo claro. Verifique el maestro con "git log" nuevamente, su fixed_destination_commit debería estar en la parte superior de la lista.

De nada (de antemano;))

ACTUALIZAR:

Ahora, los cambios que había hecho antes de que comenzaran todos estos, ahora se han ido. Si desea recuperar esos trabajos duros nuevamente, es posible. Gracias a los comandos git reflog y git cherry-pick .

Para eso, sugeriría seguir este blog o esta publicación .

kmonsoor
fuente
es una buena medida especificar el control remoto y la rama también cuando se hace "git push -f", pero "git push -f" funcionará de todos modos la mayor parte del tiempo
Robson
8

git reset HEAD~1si no desea que se vayan sus cambios (cambios no organizados). Cambiar, comprometerse y presionar nuevamentegit push -f [origin] [branch]

softvar
fuente
3

Puedes hacer un rebase interactivo:

git rebase -i <commit>

Esto abrirá su editor predeterminado. Simplemente elimine la línea que contiene la confirmación que desea eliminar para eliminar esa confirmación.

Por supuesto, también necesitará acceso al repositorio remoto para aplicar este cambio allí.

Ver esta pregunta: Git: eliminar confirmaciones seleccionadas del repositorio

Jack Edmonds
fuente
3

Intenta usar

git reset --hard <commit id> 

Tenga en cuenta: aquí la identificación de confirmación será la identificación de la confirmación a la que desea acceder, pero no la identificación que desea restablecer. Este fue el único punto donde también me quedé atrapado.

luego empujar

git push -f <remote> <branch>
Mohit Dhawan
fuente
2

Alternativamente:

git push origin +364705c23011b0fc6a7ca2d80c86cef4a7c4db7ac8^:master

Forzar la rama maestra del repositorio remoto de origen al padre de la última confirmación

MicRum
fuente