¿Cómo revierto un repositorio de Git a una confirmación previa?

7630

¿Cómo vuelvo de mi estado actual a una instantánea realizada en una confirmación determinada?

Si lo hago git log, obtengo el siguiente resultado:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <[email protected]>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <[email protected]>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <[email protected]>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <[email protected]>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

¿Cómo vuelvo al commit desde el 3 de noviembre, es decir, commit 0d1d7fc?

Serbio loco
fuente
116
Aquí hay una publicación muy clara y completa sobre cómo deshacer cosas en git, directamente desde Github.
Nobita
3
Relacionado: Rollback a un viejo Git commit en un repositorio público . Tenga en cuenta que esa pregunta agrega una restricción de que el repositorio es público.
58
Me encanta git, pero el hecho de que haya 35 respuestas a algo que debería ser increíblemente simple expone un gran problema con git. ¿O son los documentos?
The Muffin Man
2
¿Cómo es el lenguaje "trampa" en el uso de la palabra para revertir como coloquialmente significa restablecer ni siquiera se ha abordado aquí? ¿6594 votos positivos hasta ahora y no una edición de esta manera, para enfatizar la diferencia? No sería más confuso referirse a "guardar un archivo" aquí con la expresión "cometer" ...
RomainValeri

Respuestas:

9732

Esto depende mucho de lo que quiere decir con "revertir".

Cambiar temporalmente a una confirmación diferente

Si desea volver temporalmente a él, perder el tiempo, luego volver a donde está, todo lo que tiene que hacer es verificar la confirmación deseada:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

O si desea realizar confirmaciones mientras está allí, continúe y cree una nueva rama mientras lo hace:

git checkout -b old-state 0d1d7fc32

Para volver a donde estabas, solo revisa la rama en la que estabas nuevamente. (Si ha realizado cambios, como siempre al cambiar de sucursal, tendrá que lidiar con ellos según corresponda. Puede reiniciar para tirarlos; puede guardar, pagar, guardar pop para llevarlos con usted; puede comprometerse si quieres una rama allí).

Hard eliminar confirmaciones no publicadas

Si, por otro lado, quieres deshacerte de todo lo que has hecho desde entonces, hay dos posibilidades. Uno, si no ha publicado ninguna de estas confirmaciones, simplemente restablezca:

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

Si comete un error, ya ha descartado sus cambios locales, pero al menos puede volver a donde estaba antes reiniciando nuevamente.

Deshacer confirmaciones publicadas con nuevas confirmaciones

Por otro lado, si ha publicado el trabajo, probablemente no quiera restablecer la rama, ya que eso es reescribir el historial de manera efectiva. En ese caso, podría revertir los commits. Con Git, revert tiene un significado muy específico: crea un commit con el parche inverso para cancelarlo. De esta manera no reescribes ningún historial.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

La página de git-revertmanual en realidad cubre mucho de esto en su descripción. Otro enlace útil es esta sección de git-scm.com que trata sobre git-revert .

Si decide que no desea revertir después de todo, puede revertir la reversión (como se describe aquí) o restablecerla antes de la reversión (consulte la sección anterior).

También puede encontrar útil esta respuesta en este caso:
¿Cómo mover HEAD de regreso a una ubicación anterior? (Cabeza separada)

Cascabel
fuente
118
@ Comentarios de Rod sobre git revert HEAD~3como el mejor wat a invertir de nuevo 3cometa, está am importante convención.
Nueva Alejandría
20
¿Podrías escribir el número entero? como:git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Hablado el
16
@MathiasMadsenStav Sí, por supuesto, puede especificar confirmaciones mediante el SHA1 completo. Utilicé hashes abreviados para hacer que la respuesta sea más legible, y también tiendes a usarlos si estás escribiendo. Si está copiando y pegando, utilice el hash completo. Consulte Especificación de revisiones en man git rev-parse para obtener una descripción completa de cómo puede nombrar commits.
Cascabel
59
Puede usar git revert --no-commit hash1 hash2 ...y después de esto solo confirmar cada reversión en una confirmacióngit commit -m "Message"
Mirko Akov
66
¿Qué significa 'publicar' en este contexto?
Howiecamp
1852

Muchas respuestas complicadas y peligrosas aquí, pero en realidad es fácil:

git revert --no-commit 0766c053..HEAD
git commit

Esto revertirá todo, desde el HEAD de nuevo al hash de confirmación, lo que significa que volverá a crear ese estado de confirmación en el árbol de trabajo como si cada confirmación desde entonces se hubiera retirado. Luego puede confirmar el árbol actual, y creará una nueva confirmación esencialmente equivalente a la confirmación a la que "revierte".

(La --no-commitbandera le permite a git revertir todas las confirmaciones a la vez; de lo contrario, se le solicitará un mensaje para cada confirmación en el rango, llenando su historial con nuevas confirmaciones innecesarias).

Esta es una manera segura y fácil de retroceder a un estado anterior . No se destruye ningún historial, por lo que puede usarse para compromisos que ya se han hecho públicos.

Yarin
fuente
23
Si realmente desea tener confirmaciones individuales (en lugar de revertir todo con una gran confirmación), puede pasar en --no-editlugar de --no-commit, para que no tenga que editar un mensaje de confirmación para cada reversión.
88
Si una de las confirmaciones entre 0766c053..HEAD es una fusión, aparecerá un error emergente (relacionado con no -m especificado). Esto puede ayudar a aquellos que se encuentran con eso: stackoverflow.com/questions/5970889/…
timhc22
77
Para ver las diferencias antes de comprometer el uso git diff --cached.
John Erck
21
$ git revert --no-commit 53742ae..HEADregresafatal: empty commit set passed
Alex G
10
@AlexG es porque necesita ingresar el hash antes del que desea volver. En mi caso, los hashes eran como: 81bcc9e HEAD{0}; e475924 HEAD{1}, ...(desde git reflog), y quería deshacer lo que hice 81bcc9e, luego tuve que hacergit revert e475924..HEAD
EpicPandaForce
1611

Rogue Coder?

¿Trabajas por tu cuenta y solo quieres que funcione? Siga estas instrucciones a continuación, han funcionado de manera confiable para mí y para muchos otros durante años.

¿Trabajando con otros? Git es complicado. Lea los comentarios debajo de esta respuesta antes de hacer algo precipitado.

Revertir la copia de trabajo a la confirmación más reciente

Para volver a una confirmación anterior, ignorando cualquier cambio:

git reset --hard HEAD

donde HEAD es el último commit en tu rama actual

Revertir la copia de trabajo a una confirmación anterior

Para volver a una confirmación anterior a la confirmación más reciente:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Los créditos van a una pregunta similar de desbordamiento de pila, ¿ Volver a un compromiso por un hash SHA en Git? .

boulder_ruby
fuente
33
Lo hice, pero luego no pude comprometerme y empujar al repositorio remoto. Quiero que una persona mayor específica se convierta en HEAD ...
Lennon
77
Significa que ya ha introducido las confirmaciones que desea revertir. Puede crear muchos problemas para las personas que han revisado su código y están trabajando en él. Dado que no pueden aplicar su compromiso sin problemas sobre el de ellos. En tal caso, mejor hacer un git revert. Si eres el único que usa el repositorio. Haz un git push -f (pero piénsalo dos veces antes de hacerlo)
vinothkr
66
Yo sólo quiero también señalar que, como alternativa para la solución de restablecimiento automático, en vez de hacer un restablecimiento mezclado primero y un restablecimiento último, se puede hacer realidad el restablecimiento completo en primer lugar, de la siguiente manera: git reset --hard 56e05fc; git reset --soft HEAD@{1}; git commit.
55
@nuton linus paulándose a sí mismo, el creador de git, lo criticó por ser demasiado complicado. Está en el registro diciendo que estaba "sorprendido". El git se hizo tan popular dada su complejidad
Boulder_ruby
55
@boulder_ruby Creo que querías decir que Linus Torvalds fue el creador de git. Pero creo que Linus Pauling probablemente estaría de acuerdo en que git es complicado.
Suncat2000
215

La mejor opción para mí y probablemente para otros es la opción de reinicio de Git:

git reset --hard <commidId> && git clean -f

¡Esta ha sido la mejor opción para mí! ¡Es simple, rápido y efectivo!


** Nota: ** Como se mencionó en los comentarios, no haga esto si comparte su sucursal con otras personas que tienen copias de las confirmaciones anteriores

También de los comentarios, si quisieras un método menos 'ballzy' podrías usar

git clean -i
Pogrindis
fuente
37
Advertencia obligatoria: no haga esto si está compartiendo su rama con otras personas que tienen copias de las confirmaciones anteriores, porque el uso de un restablecimiento completo como este les obligará a tener que volver a sincronizar su trabajo con la rama recién restablecida. Para obtener una solución que explica en detalle cómo revertir las confirmaciones de forma segura sin perder el trabajo con un restablecimiento completo, consulte esta respuesta .
77
Secundo la advertencia de @ Cupcake ... sé muy consciente de las consecuencias. Sin embargo, tenga en cuenta que si su necesidad realmente es hacer que esas confirmaciones desaparezcan del historial para siempre, este método de reinicio + limpieza lo hará, y necesitará forzar sus ramas modificadas a todos y cada uno de los controles remotos.
ashnazg
55
git clean -f PELIGRO PELIGRO
Tisch
2
Esto establece el encabezado de mi copia local en el commit deseado. Pero entonces no puedo impulsar ningún cambio porque está detrás del control remoto. Y si saco del control remoto, termina de nuevo donde estaba en la última confirmación en la rama remota. ¿Cómo borro completamente (de todas partes) varias confirmaciones en mi copia local que se han enviado?
Ade
2
@Ade ... Podría usar la git push -fbandera ... Pero tenga cuidado, anulará el control remoto ... Asegúrese de saber lo que quiere hacer ...
Pogrindis
176

Antes de responder agreguemos algunos antecedentes, explicando de qué se HEADtrata.

First of all what is HEAD?

HEADes simplemente una referencia a la confirmación actual (más reciente) en la rama actual. Solo puede haber una sola HEADen un momento dado (excluyendo git worktree).

El contenido de HEADse almacena dentro .git/HEADy contiene los 40 bytes SHA-1 de la confirmación actual.


detached HEAD

Si no está en la última confirmación, lo que significa que HEADapunta a una confirmación previa en el historial se llama detached HEAD.

Ingrese la descripción de la imagen aquí

En la línea de comando se verá así: SHA-1 en lugar del nombre de la rama ya HEADque no apunta a la punta de la rama actual:

Ingrese la descripción de la imagen aquí


Algunas opciones sobre cómo recuperarse de un HEAD separado:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Esto verificará la nueva rama que apunta a la confirmación deseada. Este comando pagará a un commit dado.

En este punto, puede crear una rama y comenzar a trabajar desde este punto en adelante:

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Siempre puedes usar el reflogtambién. git reflogmostrará cualquier cambio que haya actualizado HEADy revisando la entrada de reflog deseada establecerá el HEADrespaldo de este commit.

Cada vez que se modifique el HEAD habrá una nueva entrada en el reflog

git reflog
git checkout HEAD@{...}

Esto lo llevará de regreso a su compromiso deseado

Ingrese la descripción de la imagen aquí


git reset HEAD --hard <commit_id>

"Mueva" su cabeza hacia atrás al compromiso deseado.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Nota: ( desde Git 2.7 ) también puedes usar el git rebase --no-autostash.

Este esquema ilustra qué comando hace qué. Como puede ver allí reset && checkoutmodifique el HEAD.

Ingrese la descripción de la imagen aquí

CodeWizard
fuente
66
Excelente pista para git reflog, eso es exactamente lo que necesitaba
smac89
44
¡Ay! Todo esto parece terriblemente complicado ... ¿no hay un comando simple que simplemente te lleve un paso atrás en el proceso? ¿Como pasar de la versión 1.1 en su proyecto a la versión 1.0? Esperaría algo como: git stepback_one_commit o algo ...
Kokodoko
hay: git reset HEAD^--hard`
CodeWizard
3
@Kokodoko Sí, es terriblemente complicado ... y un ejemplo perfecto de la poca consideración que los expertos tienen para las personas que recién comienzan. Consulte mi respuesta aquí y también el libro que recomiendo. Git NO es algo que solo puedas aprender intuitivamente. Y puedo estar absolutamente seguro de que CodeWizard no lo hizo.
Mike roedor
145

Si desea "deshacer", borrar el último mensaje de confirmación y volver a colocar los archivos modificados en etapas, usaría el comando:

git reset --soft HEAD~1
  • --softindica que los archivos no confirmados deben conservarse como archivos de trabajo opuestos a los --hardque los descartarían.
  • HEAD~1Es el último commit. Si desea revertir 3 confirmaciones que podría usar HEAD~3. Si desea revertir a un número de revisión específico, también puede hacerlo utilizando su hash SHA.

Este es un comando extremadamente útil en situaciones en las que cometió algo incorrecto y desea deshacer ese último compromiso.

Fuente: http://nakkaya.com/2009/09/24/git-delete-last-commit/

Stephen Ostermiller
fuente
3
Esto es suave y gentil: sin riesgos si no ha empujado su trabajo
nilsM
124

Puede hacerlo mediante los dos comandos siguientes:

git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

Eliminará su compromiso anterior de Git.

Si desea conservar sus cambios, también puede usar:

git reset --soft [previous Commit SHA id here]

Entonces guardará tus cambios.

kiran boghra
fuente
2
Intenté 1/2 docena de respuestas en esta publicación hasta que llegué a esta ... todas esas otras, mi configuración de git seguía dándome un error al intentar presionar. Esta respuesta funcionó. ¡Gracias!
Gene Bo
Un detalle para mí fue que perdí las diferencias ... que quería conservar para ver lo que había hecho en el commit que no funcionó. Así que la próxima vez simplemente guardaría esos datos antes de emitir este comando de reinicio
Gene Bo
1
Esta fue la única forma para deshacer una mala fusión, revertir no funcionó en ese caso. ¡Gracias!
Dave Cole
La mejor respuesta. Gracias
Imran Pollob
La mejor respuesta, gracias.
usuario1394
114

He intentado muchas formas de revertir los cambios locales en Git, y parece que esto funciona mejor si solo desea volver al último estado de confirmación.

git add . && git checkout master -f

Breve descripción:

  • NO creará ningún commit como lo git reverthace.
  • NO separará su CABEZA como lo git checkout <commithashcode>hace.
  • ANULARÁ todos sus cambios locales y BORRARÁ todos los archivos agregados desde la última confirmación en la rama.
  • Funciona solo con nombres de sucursales, por lo que puede volver solo a la última confirmación en la rama de esta manera.

Encontré una manera mucho más conveniente y simple de lograr los resultados anteriores:

git add . && git reset --hard HEAD

donde HEAD apunta a la última confirmación en su sucursal actual.

Es el mismo código de código que sugirió boulder_ruby, pero he agregado git add .antes git reset --hard HEADpara borrar todos los archivos nuevos creados desde la última confirmación, ya que esto es lo que la mayoría de la gente espera que creo cuando vuelvo a la última confirmación.

Roman Minenok
fuente
83

OK, volver a un commit anterior en Git es bastante fácil ...

Revertir sin guardar los cambios:

git reset --hard <commit>

Vuelva atrás manteniendo los cambios:

git reset --soft <commit>

Explicación: utilizando git reset, puede restablecer a un estado específico. Es común usarlo con un hash de confirmación como se ve arriba.

Pero como puede ver, la diferencia es usar las dos banderas --softy --hard, por defecto, git resetusar la --softbandera, pero es una buena práctica usar siempre la bandera, explico cada bandera:


--suave

El indicador predeterminado, como se explicó, no necesita proporcionarlo, no cambia el árbol de trabajo, pero agrega todos los archivos modificados listos para confirmar, por lo que vuelve al estado de confirmación que los cambios en los archivos no se organizan.


--difícil

Ten cuidado con esta bandera. ¡Restablece el árbol de trabajo y todos los cambios en los archivos rastreados y todo desaparecerá!


También creé la imagen a continuación que puede suceder en la vida real trabajando con Git:

Git restablecer a una confirmación

Alireza
fuente
El valor predeterminado de git resetes git reset --mixed, no git reset --soft. Verifique ¿Cuál es la diferencia entre git reset --mixed, --soft y --hard? y en inglés simple, ¿qué hace "git reset"?
Fabio dice reinstalar a Mónica el
70

Suponiendo que está hablando de master y en esa rama respectiva (dicho esto, podría ser cualquier rama de trabajo que le interese):

# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

# Reset remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

Encontré la respuesta en una publicación de blog (ahora ya no existe)

Tenga en cuenta que esto es Restablecer y forzar el cambio al control remoto, de modo que si otros miembros de su equipo ya se han retirado, les causará problemas. Estás destruyendo el historial de cambios, que es una razón importante por la cual las personas usan git en primer lugar.

Es mejor usar revertir (ver otras respuestas) que restablecer. Si eres un equipo de un solo hombre, entonces probablemente no importe.

markreyes
fuente
66
¿Cómo es esta respuesta diferente a la miríada de otros?
Matsmath
Eso es lamentable. Le envié un correo electrónico al blogger, ¡espero que aún lo tenga!
markreyes
2
Falta la sintaxis de inserción en la mayoría de las otras sugerencias sobre cómo solucionar esto. Funcionó muy bien.
jpa57
61

Digamos que tiene las siguientes confirmaciones en un archivo de texto llamado ~/commits-to-revert.txt(solía git log --pretty=onelineobtenerlas)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

Cree un script de shell Bash para revertir cada uno de ellos:

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

Esto revierte todo al estado anterior, incluidas las creaciones de archivos y directorios, y las eliminaciones, lo compromete a su rama y conserva el historial, pero lo ha vuelto a la misma estructura de archivos. Por qué Git no tiene un git revert --to <hash>está más allá de mí.

Lance Caraccioli
fuente
41
Podrías hacer una git revert HEAD~3para eliminar los últimos 3 commits
Rod
25
@ Rod - No, eso no está bien. Ese comando revertirá el commit que es el tercer abuelo de HEAD (no los últimos tres commits).
kflorence
1
@kflorence Ok, gracias por la información. Funcionaria git revert -n master~3..master~1? (Como se ve en kernel.org/pub/software/scm/git/docs/git-revert.html )
Rod
3
@ Rod - Eso suena bien, seguro que es una sintaxis fea, ¿no? Siempre he encontrado verificar el commit al que quiero "revertir" y luego hacerlo más intuitivo.
kflorence
77
Hay una manera mucho más fácil de hacer esto ahora que con un script como este, solo use git revert --no-commit <start>..<end>, porque git revertacepta un rango de confirmación en las nuevas (o todas) versiones de Git. Tenga en cuenta que el inicio del rango no está incluido en la reversión.
58

Alternativas adicionales a las soluciones de Jefromi

Las soluciones de Jefromi son definitivamente las mejores, y definitivamente debes usarlas. Sin embargo, en aras de la exhaustividad, también quería mostrar estas otras soluciones alternativas que también se pueden utilizar para revertir un compromiso (en el sentido de que crea un nuevo compromiso que deshace los cambios en el compromiso anterior , al igual que lo git reverthace).

Para ser claros, estas alternativas no son la mejor manera de revertir los commits , las soluciones de Jefromi lo son , pero solo quiero señalar que también puede usar estos otros métodos para lograr lo mismo git revert.

Alternativa 1: Restablecimientos duros y suaves

Esta es una versión muy ligeramente modificada de la solución de Charles Bailey para volver a un commit por un hash SHA en Git. :

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}

# Commit the changes
git commit -m "Revert to <commit>"

Básicamente, esto funciona al usar el hecho de que los reinicios suaves dejarán el estado de la confirmación previa en el índice / área de ensayo, que luego puede confirmar.

Alternativa 2: eliminar el árbol actual y reemplazarlo por uno nuevo

Esta solución proviene de la solución de svick para Checkout old commit y convertirlo en un nuevo commit :

git rm -r .
git checkout <commit> .
git commit

De manera similar a la alternativa # 1, esto reproduce el estado de <commit>la copia de trabajo actual. Es necesario hacerlo git rmprimero porque git checkoutno eliminará los archivos que se han agregado desde entonces <commit>.

user456814
fuente
Sobre la Alternativa 1, una pregunta rápida: al hacerlo, no perdemos entre confirmaciones, ¿verdad?
Bogac
2
@Bogac: los puntos indican una ruta de archivo, en este caso el directorio actual, por lo que se supone que lo está ejecutando desde la raíz de su copia de trabajo.
Tom
La advertencia se repite varias veces en la respuesta, pero alguien podría agregar por qué estas no son la mejor manera , en comparación, con algo como la git revert HEAD~2..HEADsolución vinculada de @ Cascabel (@ Jefromi). No estoy viendo el problema.
Joshua Goldberg
55

Aquí hay una manera mucho más simple de volver a un commit anterior (y tenerlo en un estado no comprometido, para hacer lo que quiera):

git reset HEAD~1

Por lo tanto, no hay necesidad de commit id y así sucesivamente :)

Paul Walczewski
fuente
no funcionó, un git pull después de esto arroja: error: sus cambios locales en los siguientes archivos se sobrescribirán por fusión:
malhal
1
@malhal Eso es porque has tenido cambios no confirmados. Guárdelos / reinícielos y luego funcionará sin ese error.
Paul Walczewski
39

Hay un comando (que no forma parte del núcleo de Git, pero está en el paquete git-extras ) específicamente para revertir y organizar confirmaciones antiguas:

git back

Según la página de manual , también se puede usar como tal:

# Remove the latest three commits
git back 3
Hombre de la sombra
fuente
38

La mejor manera es:

git reset --hard <commidId> && git push --force

Esto restablecerá la rama a la confirmación específica y luego cargará el servidor remoto con las mismas confirmaciones que tiene en local (esto eliminará completamente los comandos después de esa confirmación específica)

Tenga cuidado con el --forceindicador que elimina todas las confirmaciones posteriores después de la confirmación seleccionada sin la opción de recuperarlas.

david.t_92
fuente
3
trabajó como encanto!
Gaurav Gupta
Me downvoted porque no puedo ver cómo su respuesta proporciona ninguna nueva información no está ya da por ejemplo en stackoverflow.com/a/37145089/1723886 , stackoverflow.com/a/27438379/1723886 o stackoverflow.com/a/48756719/1723886 . De hecho, la mayoría de los commits ya mencionan git reset --hard, y muchos más mencionan el uso de --force o -f para presionar.
Alex Telon
Hace el trabajo con un solo comando, claro y simple. Eres libre de votar mi respuesta si no te gusta.
david.t_92
1
Otra opción a considerar para el futuro es sugerir una edición en una respuesta anterior o agregar un comentario que diga que 'esto también se puede hacer en una línea usando &&' por ejemplo. De esa manera, todos pueden ver la respuesta mejorada en un solo lugar.
Alex Telon
36

Después de todos los cambios, cuando presiona todos estos comandos, es posible que deba usar:

git push -f ...

Y no sólo git push.

sivi
fuente
15
Advertencia obligatoria: no haga esto si está compartiendo su rama con otras personas que tienen copias de las confirmaciones anteriores, porque usar un impulso de fuerza como este los obligará a tener que volver a sincronizar su trabajo. Para obtener una solución que explica en detalle cómo revertir las confirmaciones de forma segura sin perder el trabajo con un impulso forzado, consulte esta respuesta .
3
A veces esto es lo que quieres. Ejemplo: comprometido y enviado varias confirmaciones a la rama incorrecta (rama A). Después de seleccionar la rama B, quiero que estas confirmaciones se eliminen de la rama A. No quisiera revertir, ya que la reversión se aplicaría más tarde cuando las ramas A y B se fusionen. Al hacer un reinicio --hard <commitId> en la rama A seguido de un empuje forzado, se eliminan estas confirmaciones de la rama mientras se conservan en la rama B. Puedo salirse con la suya porque sé que nadie más se está desarrollando en la rama A.
Doug R
¡Gracias! No pude encontrar la manera de hacer que la rama remota coincida con mi rama local, solo necesitaba hacer un esfuerzo forzado.
Mido
32

Puede completar todos estos pasos iniciales usted mismo y regresar al repositorio de Git.

  1. Extraiga la última versión de su repositorio de Bitbucket con el git pull --allcomando

  2. Ejecute el comando de registro Git con -n 4desde su terminal. El número después de -ndetermina el número de confirmaciones en el registro a partir de la confirmación más reciente en su historial local.

    $ git log -n 4
    
  3. Restablezca el encabezado del historial de su repositorio utilizando git reset --hard HEAD~Ndonde N es el número de confirmaciones que desea recuperar. En el siguiente ejemplo, el encabezado se retrasará una confirmación, a la última confirmación en el historial del repositorio:

  4. Empuje el cambio al repositorio de Git usando git push --forcepara forzar el cambio.

Si quieres el repositorio de Git para una confirmación previa:

git pull --all
git reset --hard HEAD~1
git push --force
Nanhe Kumar
fuente
30

Vuelva a la confirmación más reciente e ignore todos los cambios locales:

git reset --hard HEAD
Mohammed Irfan Tirupattur
fuente
28

Seleccione su compromiso requerido y verifíquelo

git show HEAD
git show HEAD~1
git show HEAD~2 

hasta que obtenga el compromiso requerido. Para que el HEAD señale eso, haz

git reset --hard HEAD~1

o git reset --hard HEAD~2o lo que sea.

tonythomas01
fuente
77
Advertencia obligatoria: no haga esto si está compartiendo su rama con otras personas que tienen copias de las confirmaciones anteriores, porque el uso de un restablecimiento completo como este les obligará a volver a sincronizar su trabajo con la rama recién restablecida. Para obtener una solución que explica en detalle cómo revertir las confirmaciones de forma segura sin perder el trabajo con un restablecimiento completo, consulte esta respuesta .
2
Además, para ser claros, git show HEADes equivalente a solo usar git log HEAD -1.
25

Si la situación es urgente y solo desea hacer lo que el interrogador le pidió de manera rápida y sucia , suponiendo que su proyecto se encuentre en un directorio llamado, por ejemplo, "mi proyecto":


RÁPIDO Y SUCIO : dependiendo de las circunstancias, rápido y sucio puede ser muy BUENO. Lo que mi solución aquí es NO reemplazar irreversiblemente los archivos que tiene en su directorio de trabajo con archivos recogidos / extraídos de las profundidades del repositorio git que acechan debajo de su directorio .git / usando comandos git diabólicamente inteligentes y diabólicamente poderosos, de los cuales hay muchos. NO TIENE QUE HACER TAL BUCEO EN EL MAR PROFUNDO PARA RECUPERAR lo que puede parecer una situación desastrosa, e intentar hacerlo sin la suficiente experiencia puede resultar fatal .


  1. Copie todo el directorio y llámelo de otra manera, como "mi proyecto - copiar". Suponiendo que sus archivos de repositorio git ("repo") se encuentran en el directorio "mi proyecto" (el lugar predeterminado para ellos, en un directorio llamado ".git"), ahora habrá copiado tanto sus archivos de trabajo como sus archivos repo.

  2. Haga esto en el directorio "mi proyecto":

    .../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

Esto devolverá el estado del repositorio en "mi proyecto" a lo que era cuando realizó esa confirmación (una "confirmación" significa una instantánea de sus archivos de trabajo). Todos los commits desde entonces se perderán para siempre bajo "mi proyecto", PERO ... todavía estarán presentes en el repositorio bajo "mi proyecto - copia" ya que usted copió todos esos archivos, incluidos los que están bajo ... /. Git /.

Luego tiene dos versiones en su sistema ... puede examinar o copiar o modificar archivos de interés, o lo que sea, de la confirmación anterior. Puede descartar completamente los archivos en "mi proyecto - copiar", si ha decidido que el nuevo trabajo ya que la confirmación restaurada no iba a ninguna parte ...

Lo obvio si desea continuar con el estado del proyecto sin descartar realmente el trabajo, ya que esta confirmación recuperada es cambiar el nombre de su directorio nuevamente: elimine el proyecto que contiene la confirmación recuperada (o déle un nombre temporal) y cambie el nombre de su " mi proyecto: copie el directorio "volver a" mi proyecto ". Entonces, quizás intente comprender algunas de las otras respuestas aquí, y probablemente haga otra confirmación bastante pronto.

Git es una creación brillante, pero absolutamente nadie es capaz de "recogerlo sobre la marcha": también las personas que intentan explicarlo con demasiada frecuencia asumen conocimientos previos de otros VCS [Sistemas de control de versiones] y profundizan demasiado. demasiado pronto, y cometer otros delitos, como el uso de términos intercambiables para "retirar", en formas que a veces parecen calculadas para confundir a un principiante.

Para ahorrarte mucho estrés, aprende de mis cicatrices. Tienes que leer un libro sobre Git. Recomiendo "Control de versiones con Git" . Hazlo más temprano que tarde. Si lo hace, tenga en cuenta que gran parte de la complejidad de Git proviene de la ramificación y la reemergencia: puede omitir esas partes en cualquier libro. Según su pregunta, no hay ninguna razón por la cual la gente deba cegarlo con la ciencia .

¡Especialmente si, por ejemplo, esta es una situación desesperada y eres un novato con Git!

PD: Otro pensamiento: (ahora) en realidad es bastante simple mantener el repositorio de Git en un directorio que no sea el que tiene los archivos de trabajo. Esto significaría que no tendría que copiar todo el repositorio de Git utilizando la solución rápida y sucia anterior. Vea la respuesta de Fryer usando --separate-git-dir aquí . Sin embargo, tenga en cuenta: si tiene un repositorio de "directorio separado" que no copia, y realiza un restablecimiento completo, todas las versiones posteriores a la confirmación de restablecimiento se perderán para siempre, a menos que tenga, como debería, realiza copias de seguridad de su repositorio regularmente, preferiblemente en la nube (por ejemplo, Google Drive ) entre otros lugares.

Sobre este tema de "copia de seguridad en la nube", el siguiente paso es abrir una cuenta (gratis, por supuesto) con GitHub o (mejor en mi opinión) GitLab . A continuación, puede hacer un git pushcomando regularmente para que su repositorio de Cloud esté actualizado "correctamente". Pero nuevamente, hablar de esto puede ser demasiado pronto.

Mike roedor
fuente
23

Esta es una forma más de restablecer directamente a una confirmación reciente

git stash
git stash clear

Borra directamente todos los cambios que ha estado realizando desde la última confirmación.

PD: tiene un pequeño problema; También elimina todos los cambios almacenados recientemente. Lo cual supongo que en la mayoría de los casos no debería importar.

Redes de puntos
fuente
NOTA: Los archivos nuevos no agregados en el índice no se guardan. También debe agregarlos o eliminarlos manualmente.
andreyro
¿Por qué oh por qué limpiar el alijo? Además de no ser una solución, esto es realmente dañino. La lectura de la primera oración de la pregunta invalida inmediatamente la solución oculta (que podría ser útil SOLO para restablecer la ÚLTIMA confirmación).
RomainValeri
22

Para limpiar completamente el directorio de un codificador de algunos cambios accidentales, utilizamos:

git add -A .
git reset --hard HEAD

Simplemente git reset --hard HEADeliminará las modificaciones, pero no eliminará los archivos "nuevos". En su caso, arrastraron accidentalmente una carpeta importante en algún lugar al azar, y todos esos archivos estaban siendo tratados como nuevos por Git, por reset --hardlo que no lo solucionó. Al ejecutar el git add -A .comando de antemano, los rastreó explícitamente a todos con git, para ser borrados por el reinicio.

Chris Moschini
fuente
21

Para mantener los cambios de la confirmación anterior en HEAD y pasar a la confirmación anterior, haga lo siguiente:

git reset <SHA>

Si no se requieren cambios de la confirmación anterior a HEAD y simplemente descarta todos los cambios, haz lo siguiente:

git reset --hard <SHA>
Vishnu Atrai
fuente
20

Creo que algunas personas pueden llegar a esta pregunta que desean saber cómo deshacer los cambios comprometidos que han realizado en su maestro, es decir, tirar todo y volver al origen / maestro, en cuyo caso, haga esto:

git reset --hard origin/master

/superuser/273172/how-to-reset-master-to-origin-master

Nevster
fuente
18

Revertir es el comando para deshacer las confirmaciones.

git revert <commit1> <commit2> 

Muestra:

git revert 2h3h23233

Es capaz de tomar el alcance de la CABEZA como a continuación. Aquí 1 dice "revertir la última confirmación".

git revert HEAD~1..HEAD

y luego hacer git push

Sireesh Yarlagadda
fuente
14

Intenta restablecer la confirmación deseada:

git reset <COMMIT_ID>

(para verificar el uso de COMMIT_ID git log)

Esto restablecerá todos los archivos modificados al estado no agregado.

Ahora puede checkouteliminar todos los archivos sin agregar

git checkout .

Verifique git logpara verificar sus cambios.

ACTUALIZAR

Si tiene uno y solo se compromete en su repositorio, intente

git update-ref -d HEAD

optimistanoop
fuente
13

A medida que sus confirmaciones se envían de forma remota, debe eliminarlas. Déjame asumir que tu rama se desarrolla y se empuja sobre el origen .

Primero debe eliminar el desarrollo del origen :

git push origin :develop (note the colon)

Entonces necesita desarrollar el estado que desea, déjeme asumir que el hash de confirmación es EFGHIJK:

git reset --hard EFGHIJK

Por último, empuje desarrollar de nuevo:

git push origin develop
George Ninan
fuente
13

¡Precaución! Este comando puede causar la pérdida del historial de confirmación si el usuario realiza la confirmación incorrecta por error. Siempre tenga una copia de seguridad adicional de su git en otro lugar, en caso de que cometa errores, entonces está un poco más seguro. :)

He tenido un problema similar y quería volver a una confirmación anterior. En mi caso no estaba interesado en mantener el commit más nuevo, por lo tanto, lo usé Hard.

Así es como lo hice:

git reset --hard CommitId && git clean -f

Esto revertirá en el repositorio local, y aquí después de usar git push -factualizará el repositorio remoto.

git push -f
maytham-ɯɐɥʇʎɐɯ
fuente
13

En GitKraken puedes hacer esto:

  1. Haga clic derecho en la confirmación que desea restablecer, elija: Restablecer esta confirmación / Difícil :

    Ingrese la descripción de la imagen aquí

  2. Haga clic derecho en el commit nuevamente, elija: Nombre de la sucursal actual / Push :

    Ingrese la descripción de la imagen aquí

  3. Haga clic en Force Push :

    Ingrese la descripción de la imagen aquí

Obs. : Debe tener cuidado, porque se pierde todo el historial de confirmación después del restablecimiento completo y esta acción es irreversible. Necesitas estar seguro de lo que estás haciendo.

Ângelo Polotto
fuente
11

Si desea corregir algún error en la última confirmación, una buena alternativa sería usar el comando git commit --amend . Si el último commit no está señalado por ninguna referencia, esto hará el truco, ya que crea un commit con el mismo padre que el último commit. Si no hay referencia a la última confirmación, simplemente se descartará y esta confirmación será la última confirmación. Esta es una buena manera de corregir confirmaciones sin revertir confirmaciones. Sin embargo, tiene sus propias limitaciones.

Upul Doluweera
fuente