Git - Deshacer confirmaciones empujadas


610

Tengo un proyecto en un repositorio remoto, sincronizado con un repositorio local (desarrollo) y el servidor (prod). He estado haciendo algunos cambios comprometidos que ya se enviaron al control remoto y se retiraron del servidor. Ahora, quiero deshacer esos cambios. Así que podría git checkoutconfirmar antes de los cambios y confirmar los nuevos cambios, pero supongo que habrá problemas para empujarlos nuevamente al control remoto. ¿Alguna sugerencia sobre cómo debo proceder?


Respuestas:


735

Puede revertir confirmaciones individuales con:

git revert <commit_hash>

Esto creará una nueva confirmación que revierte los cambios de la confirmación que especificó. Tenga en cuenta que solo revierte esa confirmación específica, y no confirma después de eso. Si desea revertir un rango de confirmaciones, puede hacerlo así:

git revert <oldest_commit_hash>..<latest_commit_hash>

Revierte las confirmaciones entre e incluyendo las confirmaciones especificadas.

Mire la página de manual de git-revert para obtener más información sobre el git revertcomando. También mire esta respuesta para obtener más información sobre la reversión de confirmaciones.


22
En otras palabras, vuelve al <oldest_commit_hash>;)
David

77
@mr_jigsaw Usegit log
gitaarik

2
En la documentación de git, dice que el comando revert revierte las confirmaciones entre la primera y la última confirmación (incluidas la primera y la última). Ver documentación
Onur Demir

44
@aod es correcto, esta respuesta debe actualizarse. la API git actual para la reversión se ha <oldest_commit_hash>incluido en la lista de
reversiones

44
con git 2.17.2 revert <old> .. <new> no incluye old pero incluye <new>
chingis

353

Una solución que no guarda rastros de "deshacer".

NOTA: no haga esto si alguien ya retiró su cambio (usaría esto solo en mi repositorio personal)

hacer:

git reset <previous label or sha1>

esto volverá a verificar todas las actualizaciones localmente (por lo que el estado de git enumerará todos los archivos actualizados)

luego "hace su trabajo" y vuelve a confirmar sus cambios (Nota: este paso es opcional)

git commit -am "blabla"

En este momento su árbol local difiere del remoto

git push -f <remote-name> <branch-name>

presionará y forzará el control remoto para considerar este impulso y eliminará el anterior (especificar el nombre remoto y el nombre de la sucursal no es obligatorio, pero se recomienda evitar actualizar todas las sucursales con el indicador de actualización).

!! cuidado, algunas etiquetas todavía pueden estar apuntando eliminado commit !! cómo-eliminar-una-etiqueta-remota


44
-a todos los archivos rastreados serán confirmados -m mensaje de confirmación sigue
jo_

3
Exactamente lo que buscaba. Alguien cometió un error, presionó y lo revertió nuevamente después. Las ramas no podrían fusionarse debido a esto y yo quería conseguir el repositorio de estar en el estado correcto de nuevo (y la eliminación de la confirmación desde la historia, ya que eran los culpables de todos modos)
byemute

1
¿Qué "etiqueta anterior o sha1" debo usar? ¿Debo ingresar el último "correcto" o el anterior y volver a hacer todos los cambios realizados por el último correcto?
elysch

3
el justo antes de la comisión eroneous
jo_

1
Exactamente lo que necesito. He empujado una rama para dominar por error. Y como resultado, tuve muchos compromisos de basura durante todo el historial de compromisos. ¡Acabo de hacer la git push -fúltima confirmación correcta y el historial remoto se limpió! ¡Gracias!
Anton Rybalko

193

Lo que hago en estos casos es:

  • En el servidor, mueva el cursor hacia la última confirmación válida conocida:

    git push -f origin <last_known_good_commit>:<branch_name>
    
  • Localmente, haz lo mismo:

    git reset --hard <last_known_good_commit>
    #         ^^^^^^
    #         optional
    



Vea un ejemplo completo en una rama my_new_branchque creé para este propósito:

$ git branch
my_new_branch

Esta es la historia reciente después de agregar algunas cosas a myfile.py:

$ git log
commit 80143bcaaca77963a47c211a9cbe664d5448d546
Author: me
Date:   Wed Mar 23 12:48:03 2016 +0100

    Adding new stuff in myfile.py

commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit

Quiero deshacerme del último commit, que ya fue empujado, así que ejecuto:

$ git push -f origin b4zad078237fa48746a4feb6517fa409f6bf238e:my_new_branch
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:me/myrepo.git
 + 80143bc...b4zad07 b4zad078237fa48746a4feb6517fa409f6bf238e -> my_new_branch (forced update)

¡Agradable! Ahora veo que el archivo que fue cambiado en ese commit ( myfile.py) se muestra en "no efectuado para commit":

$ git status
On branch my_new_branch
Your branch is up-to-date with 'origin/my_new_branch'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   myfile.py

no changes added to commit (use "git add" and/or "git commit -a")

Como no quiero estos cambios, simplemente muevo el cursor hacia atrás localmente también:

$ git reset --hard b4zad078237fa48746a4feb6517fa409f6bf238e
HEAD is now at b4zad07 Initial commit

Entonces, HEAD está en el commit anterior, tanto en local como remoto:

$ git log
commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit

10
¡Esta es la respuesta correcta! esto es exactamente lo que debía hacerse en mi caso, gracias aprendí algo nuevo hoy :)
Egli Becerra

2
¡Esta es la respuesta correcta! Se trata de commits empujados (!)!
powtac

3
Si desea revertir verdaderamente los cambios (como si nunca los hubiera presionado), esta es la respuesta correcta.
Jacob

1
Respuesta perfecta. Funcionó bien como se esperaba!
RafiAlhamd

2
¡Que alguien le compre cerveza a este hombre!
Jay Nebhwani

72

Puede REVERTAR (o también puede llamarlo ELIMINAR ) el Git Commit AMBOS localmente y remotamente si sigue los pasos que se indican a continuación a través de la línea de comando git.

Ejecute el siguiente comando para ver la identificación de confirmación que desea revertir

git log --oneline --decorate --graph

Obtendrá como una siguiente captura de pantalla ingrese la descripción de la imagen aquí

Si también marca el control remoto (a través de la interfaz web) , puede ver que esto sería lo mismo que se muestra a continuación

ingrese la descripción de la imagen aquí

Según la captura de pantalla, actualmente se encuentra en commit id e110322, sin embargo, desea volver a 030bbf6, tanto LOCAL como REMOTAMENTE .

Realice los siguientes pasos para BORRAR / REVERTIR confirmaciones localmente + remotamente


Primero volviendo localmente a commit id 030bbf6

git reset --hard 030bbf6

seguido por

git clean -f -d

Estos dos comandos limpian el restablecimiento de la fuerza para comprometer la etapa 030bbf6 como se muestra a continuación en la instantánea

ingrese la descripción de la imagen aquí

ahora si ejecuta el estado de git, verá que está DOS confirmaciones DETRÁS de la rama remota como se muestra a continuación ingrese la descripción de la imagen aquí

Ejecute siguiente para actualizar sus índices (si hay alguna actualización). Se recomienda que solicite a todos los desarrolladores que no acepten ninguna solicitud de extracción en la rama remota principal.

git fetch --all

Una vez que haya terminado con él, entonces debe presionar este compromiso con fuerza usando el símbolo + delante de la rama como se muestra a continuación. Lo he usado aquí como rama maestra , puede reemplazarlo con cualquier

ingrese la descripción de la imagen aquí Código

git push -u origin +master

ahora, si ve la interfaz web del control remoto, entonces confirme allí también debería revertirse.

ingrese la descripción de la imagen aquí


61

Esto eliminará tus commits empujados

git reset --hard 'xxxxx'

git clean -f -d

git push -f

77
Este método reescribe correctamente el historial para eliminar la confirmación. Impresionante
Jesse Reza Khorasanee

2
esta respuesta es el magnifeco!
truthadjustr

3
Me encanta la respuesta, gracias :)
Dzenis H.

1
Para ser claros (no estaba seguro): la confirmación será la confirmación actual después de la operación. No es el último en eliminar.
Maik639

21
git revert HEAD -m 1

En la línea de código anterior. "El último argumento representa"

  • 1: revierte uno confirma.

  • 2: revierte las dos últimas confirmaciones.

  • n: revierte los últimos n commits.

Debe presionar después de este comando para que surta efecto en el control remoto. Tiene otras opciones, como especificar el rango de confirmaciones para revertir. Esta es una de las opciones.


Uso posterior git commit -am "COMMIT_MESSAGE" entonces git pushogit push -f


8
Esto no es cierto: el parámetro -m especifica el número de padre al que se debe revertir (normalmente 1 si desea revertir los cambios entrantes, "suyos", en lugar de 2 para los cambios fusionados, "nuestro" - para fusionar 2 se compromete). No tiene nada que ver con el número de confirmaciones revertidas; si desea revertir un rango de confirmaciones, usegit revert ref1..ref2
Referencia nula el

1
No tuvo el efecto deseado
Sam Tuke

4

2020 forma simple:

git reset <commit_hash>

(El hash de la última confirmación que desea mantener).

Mantendrá los cambios ahora no confirmados localmente.

Si quiere presionar nuevamente, debe hacer:

git push -f

0

Aquí está mi camino:

Digamos que el nombre de la rama es develop.

# Create a new temp branch based on one history commit
git checkout <last_known_good_commit_hash>
git checkout -b develop-temp

# Delete the original develop branch and 
# create a new branch with the same name based on the develop-temp branch
git branch -D develop
git checkout -b develop

# Force update this new branch
git push -f origin develop

# Remove the temp branch
git branch -D develop-temp

0

Puedes hacer algo como

git push origin +<short_commit_sha>^:<branch_name>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.