Deshaciendo un 'git push'

592

Esto es lo que hice en mi rama supuestamente estable ...

% git rebase master
First, rewinding head to replay your work on top of it...
Fast-forwarded alpha-0.3.0 to master.
% git status
# On branch alpha-0.3.0
# Your branch is ahead of 'origin/alpha-0.3.0' by 53 commits.
#
nothing to commit (working directory clean)
% git push
Fetching remote heads...
  refs/
  refs/heads/
  refs/tags/
  refs/remotes/
'refs/heads/master': up-to-date
updating 'refs/heads/alpha-0.3.0'
  from cc4b63bebb6e6dd04407f8788938244b78c50285
  to   83c9191dea88d146400853af5eb7555f252001b0
    done
'refs/heads/unstable': up-to-date
Updating remote server info

Todo eso fue un error como más tarde me di cuenta. Me gustaría deshacer todo este proceso y revertir la rama alpha-0.3.0 a lo que era.

¿Qué tengo que hacer?

Ciro
fuente
esta publicación de stackoverflow quizás? stackoverflow.com/questions/134882/undoing-a-git-rebase
Steen
44
En realidad no es la misma situación, deshacer un rebase es un escenario de repositorio local, deshacer un empuje git involucra un repositorio remoto y puede ser más complicado dependiendo del acceso que tenga.
CB Bailey
Steen, tienes razón, probablemente debería haberlo hecho, supongo. Me imaginé que el bendito repositorio del que todos extraen es más una tarea administrativa y, por lo tanto, pertenece aquí, donde git general del lado del cliente es una pregunta de stackoverflow.
Cyrus
Aclaración rápida: supongo que si te refieres a un git commit por un valor hash parcial , git asumirá que estás hablando del commit cuyo hash comienza con esa cadena.
Gershom

Respuestas:

944

Debe asegurarse de que ningún otro usuario de este repositorio obtenga los cambios incorrectos o intente construir sobre las confirmaciones que desea eliminar porque está a punto de rebobinar el historial.

Entonces necesita 'forzar' empujar la referencia anterior.

git push -f origin last_known_good_commit:branch_name

o en tu caso

git push -f origin cc4b63bebb6:alpha-0.3.0

Es posible que haya receive.denyNonFastForwardsconfigurado en el repositorio remoto. Si este es el caso, recibirá un error que incluye la frase [remote rejected].

En este escenario, tendrá que eliminar y volver a crear la rama.

git push origin :alpha-0.3.0
git push origin cc4b63bebb6:refs/heads/alpha-0.3.0

Si esto no funciona, tal vez porque lo ha receive.denyDeletesconfigurado, entonces debe tener acceso directo al repositorio. En el repositorio remoto, debe hacer algo como el siguiente comando de plomería.

git update-ref refs/heads/alpha-0.3.0 cc4b63bebb6 83c9191dea8
CB Bailey
fuente
16
Una respuesta perfecta y bien explicada: muchas gracias. Para cualquier otra persona que tropieza con esto, por razones académicas probé los dos primeros enfoques, y ambos funcionaron, obviamente si el primero funciona, es el enfoque más limpio. Si te abriera 10 veces, Charles, lo haría. :)
Cyrus
139
Para referencia rápida, la primera línea aquí esgit push -f origin last_known_good_commit:branch_name
philfreo
55
git push -f origin cc4b63bebb6: alpha-0.3.0 => este me ayudó, tenga en cuenta que alpha-0.3.0 es el nombre de la rama y cc4b63bebb6 es el id de confirmación al que deseamos volver. entonces, después de ejecutar este comando, estaremos en cc4b63bebb6 commit id.
kumar
22
Esta solución es muy peligrosa si está trabajando en un repositorio compartido. Como práctica recomendada, todas las confirmaciones enviadas a un repositorio remoto que se comparte deben considerarse "inmutables". Use 'git revert
Saboosh
1
jww: en comparación con todo lo demás, git es la herramienta de control de fuente más eficiente y rica en funciones disponible. Cada equipo lo usa de manera diferente. Vale la pena pasar un fin de semana jugando con un repositorio nuevo y revisando todos los escenarios comunes. Una vez que ha pasado algún tiempo trabajando con él, el desarrollo es mucho menos estresante.
usuario1491819
165

Creo que también puedes hacer esto:

git checkout alpha-0.3.0
git reset --hard cc4b63bebb6
git push origin +alpha-0.3.0

Esto es muy similar al último método, excepto que no tiene que perder el tiempo en el repositorio remoto.

Benny Wong
fuente
99
Esto también funcionó para mí, pero vale la pena señalar que esto "reescribirá" el historial en el control remoto. Esto puede ser lo que quieres, ¡pero puede que no lo sea!
Tom
3
+1 por esta respuesta que realmente me ayudó. También quería agregar (y dejar las cosas claras) que la ID de confirmación (que viene después del --hardparámetro " ") debería ser la ID de la confirmación a la que desea restablecer su rama.
Michael Dautermann
1
Reescribí bien la historia ... cualquiera que pudiera haber hecho los cambios, me aseguré de que lo hicieran git reset --hard [commit_id]para que no nos metiéramos con el continuo espacio-tiempo.
Alien Life Form
99
¿Para qué sirve el + en "git push origin + alpha-0.3.0"?
jpierson
1
@jpierson +obliga a que se produzca el empuje, de manera similar a -f(pero ligeramente diferente: stackoverflow.com/a/25937833/1757149 ). Sin ella, si se intenta git push origin alpha-0.3.0el empuje fallará: Updates were rejected because the tip of your current branch is behind.
A__
106

git revert es menos peligroso que algunos de los enfoques sugeridos aquí:

prompt> git revert 35f6af6f77f116ef922e3d75bc80a4a466f92650
[master 71738a9] Revert "Issue #482 - Fixed bug."
 4 files changed, 30 insertions(+), 42 deletions(-)
prompt> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
prompt>

Reemplace 35f6af6f77f116ef922e3d75bc80a4a466f92650 con su propio compromiso.

neoneye
fuente
2
¿Cómo se me ocurre la identificación 35f6af6f77f116ef922e3d75bc80a4a466f92650? Esta respuesta sería mejor si pudieras explicar eso.
Volomike
2
@Volomike (y los desarrolladores de Google del futuro), esta pregunta describe muchas formas de obtenerla: control de versiones y pregunta hash en SO
Jaime
Esta es la respuesta correcta, porque con "git reset" no debería poder presionar (las actualizaciones se rechazaron porque la punta de su rama actual está detrás de su contraparte remota) o necesita forzar el tirón que no está realmente limpio.
Thomas Decaux
Esto me estaba funcionando. Sin embargo, tenga cuidado ya que revertir revertirá todos los cambios en sus archivos locales.
user1941537
Opté por este enfoque varias veces, pero también uso git rebase -i <id-before-last-good-commit> para hacer un rebase interactivo y limpiar el historial como se sugiere aquí, stackoverflow.com/questions/5189560/… .
Ernesto Allely
35

La solución aceptada (de @charles bailey) es altamente peligrosa si está trabajando en un repositorio compartido.

Como práctica recomendada, todas las confirmaciones enviadas a un repositorio remoto que se comparte deben considerarse "inmutables". Utilice 'git revert' en su lugar: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#fixing-mistakes

https://git-scm.com/book/be/v2/Git-Basics-Undoing-Things

Saboosh
fuente
¿Cuáles son exactamente las instrucciones que prescribe? Parece que solo tienes enlaces antiguos.
jww
32

Una forma de hacerlo sin perder los cambios que quería:

git reset cc4b63b 
git stash
git push -f origin alpha-0.3.0
git stash pop

Luego puede elegir los archivos que desea enviar

curmil
fuente
19

Otra forma de hacer esto:

  1. crear otra rama
  2. pagar el commit anterior en esa rama usando "git checkout"
  3. empujar la nueva sucursal.
  4. elimine la rama anterior y presione eliminar (usar git push origin --delete <branch_name>)
  5. cambiar el nombre de la nueva rama a la antigua rama
  6. empujar de nuevo.
Rushabh Mehta
fuente
2
Esta parece una solución real cuando ya has cometido errores en el repositorio
Illarion Kovalchuk
17
git push origin +7f6d03:master

Esto revertirá su repositorio al número de confirmación mencionado

ireshika piyumalie
fuente
2
Esta es la respuesta más directa. Eres un ahorrador de vida.
Ekundayo Blessing Funminiyi
2
Recuerde, eso no restablecerá sus archivos locales.
K-Gun el
11

Deshacer confirmaciones múltiples git reset --hard 0ad5a7a6 (Solo proporcione hash SHA1 commit)

Deshacer la última confirmación

git reset --HAD HEAD ~ 1 (se eliminarán los cambios a la última confirmación) git reset --soft HEAD ~ 1 (los cambios a la última confirmación estarán disponibles como modificaciones locales no confirmadas)

Jaymin
fuente
9

Escenario 1 : si desea deshacer la última confirmación, diga 8123b7e04b3, a continuación se muestra el comando (esto funcionó para mí):

git push origin +8123b7e04b3^:<branch_name>

La salida se ve a continuación:

Total 0 (delta 0), reused 0 (delta 0)
To https://testlocation/code.git
 + 8123b7e...92bc500 8123b7e04b3^ -> master (forced update)

Información adicional: Escenario 2 : en alguna situación, es posible que desee revertir lo que acaba de deshacer (básicamente deshacer el deshacer) a través del comando anterior, luego use el siguiente comando:

git reset --hard 8123b7e04b3

Salida:

HEAD is now at cc6206c Comment_that_was_entered_for_commit

Más información aquí: https://github.com/blog/2019-how-to-undo-almost-anything-with-git

Barani r
fuente
El escenario 1 debería ser la respuesta aceptada, ya que la pregunta no especificaba qué confirmación eliminar. La respuesta aceptada solo elimina la última confirmación. Esta respuesta elimina cualquier confirmación.
Dominic Cerisano
0

Las respuestas existentes son buenas y correctas, sin embargo, ¿qué sucede si necesita deshacer el pushpero?

  1. Desea mantener las confirmaciones localmente o desea mantener los cambios no confirmados
  2. No sabes cuántos compromisos acabas de impulsar

Use este comando para revertir el cambio a la referencia:

git push -f origin refs/remotes/origin/<branch>@{1}:<branch>
Vlad274
fuente
-2

Si desea ignorar el último commit que acaba de insertar en la rama remota: esto no eliminará el commit sino que simplemente lo ignorará moviendo el puntero git al commit anterior, referido por HEAD ^ o HEAD ^ 1

git push origin +HEAD^:branch

Pero si ya ha presionado este commit, y otros han retirado la rama. En este caso, reescribir el historial de su sucursal no es deseable y, en su lugar, debe revertir esta confirmación:

git revert <SHA-1>
git push origin branch
mkebri
fuente
1
¡si! esto funcionó a las mil maravillas cuando trabajas con github. Gracias.
cukabeka
La pregunta es sobre "empujar" y luego se refiere a la rama Remota. No para mover el HEAD sobre un commit, lo que significa ignorar el último commit empujado, solo haz esto: git push origin + HEAD ^: your_branch
mkebri