ultimo - Cómo revertir un repositorio Git a un commit anterior
recuperar commit borrado (30)
¡Precaución! Este comando puede provocar la pérdida del historial de confirmación, si el usuario coloca la confirmación errónea por error. Siempre tenga una copia de seguridad adicional de su git en algún otro lugar, en caso de cometer errores, entonces estará un poco más seguro. :)
He tenido un problema similar y quise volver al Commit anterior. En mi caso, no fui designado para mantener el compromiso más reciente que utilicé Hard
.
Así es como lo hice:
git reset --hard CommitId && git clean -f
Esto revertirá en el repositorio local, aquí después de usarlo git push -f
actualizaremos el repositorio remoto.
git push -f
¿Cómo vuelvo de mi estado actual a una instantánea realizada en una confirmación determinada?
Si 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 volver al compromiso desde el 3 de noviembre, es decir, cometer 0d1d7fc
?
Alternativas extra a las soluciones de Jefromi
Las soluciones de Jefromi son definitivamente las mejores, y definitivamente debes usarlas. Sin embargo, en aras de la integridad, también quería mostrar estas otras soluciones alternativas que también se pueden usar para revertir un commit (en el sentido de que crea un nuevo commit que deshace los cambios en el commit anterior , como lo hace git revert
) .
Para ser claros, estas alternativas no son la mejor manera de revertir los compromisos , las soluciones de Jefromi sí lo son , pero solo quiero señalar que también puede usar estos otros métodos para lograr lo mismo que git revert
.
Alternativa 1: Reseteos duros y suaves
Esta es una versión muy ligeramente modificada de la solución de Charles Bailey para Revertir a un compromiso 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 utilizando el hecho de que los reinicios suaves dejarán el estado de la confirmación previa en el índice / área de almacenamiento, que luego puede confirmar.
Alternativa 2: Eliminar el árbol actual y reemplazar con el nuevo
Esta solución proviene de la solución de svick para Checkout old commit y hacer que sea un nuevo commit :
git rm -r .
git checkout <commit> .
git commit
De manera similar a la alternativa # 1, esto reproduce el estado de <commit>
en la copia de trabajo actual. Es necesario hacer git rm
primero porque git checkout
no eliminará los archivos que se han agregado desde <commit>
.
Esta es una forma más de restablecer directamente a un compromiso 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 de almacenamiento almacenados recientemente. Que supongo que en la mayoría de los casos no debería importar.
Volviendo copia de trabajo a la más reciente Commit
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 revertir 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 se dirigen a una pregunta similar de desbordamiento de pila, ¿ Desea volver a una confirmación por un hash SHA en Git? .
Antes de responder, agreguemos algunos antecedentes, explicando qué es esta HEAD
.
First of all what is HEAD?
HEAD
es simplemente una referencia al compromiso actual (más reciente) en la rama actual. Solo puede haber una sola HEAD
en un momento dado (excluyendo git worktree
).
El contenido de HEAD
se almacena dentro de .git/HEAD
, y 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 HEAD
está apuntando a una confirmación anterior en la historia, se llama detached HEAD
.
En la línea de comandos se verá así: SHA-1 en lugar del nombre de la rama ya que HEAD
no apunta a la punta de la rama actual:
Algunas opciones sobre cómo recuperarse de una CABEZA separada:
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 hará que la nueva rama apunte a la confirmación deseada. Este comando realizará el checkout a un commit dado.
En este punto, puede crear una rama y comenzar a trabajar desde este punto en:
# 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 reflog
también. git reflog
mostrará cualquier cambio que actualice el HEAD
y al verificar la entrada del reflog deseado, el HEAD
volverá a este compromiso.
Cada vez que se modifique el HEAD habrá una nueva entrada en el reflog
git reflog
git checkout HEAD@{...}
Esto te llevará de vuelta a tu compromiso deseado
git reset HEAD --hard <commit_id>
"Mueve" tu cabeza hacia atrás hasta el 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 puede usar
git rebase --no-autostash
también.
Este esquema ilustra qué comando hace qué. Como puedes ver, reset && checkout
modifica la HEAD
.
Aquí hay una forma mucho más sencilla de volver a un compromiso anterior (y tenerlo en un estado no comprometido, para hacer lo que quiera):
git reset HEAD~1
Por lo tanto, no hay necesidad de cometer IDs y así sucesivamente :)
Creo que algunas personas pueden llegar a esta pregunta queriendo saber cómo deshacer los cambios comprometidos que han hecho en su maestro, es decir, deshacerse de todo y regresar a origen / maestro, en cuyo caso, haga esto:
git reset --hard origin/master
https://superuser.com/questions/273172/how-to-reset-master-to-origin-master
Después de todos los cambios, cuando presiona todos estos comandos, es posible que tenga que usar:
git push -f ...
Y no solo git push
.
Digamos que tiene las siguientes confirmaciones en un archivo de texto llamado ~/commits-to-revert.txt
(usé git log --pretty=oneline
para obtenerlas)
fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca
Crea 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 hace que todo vuelva al estado anterior, incluidas las creaciones de archivos y directorios, y las eliminaciones, confírmelo en su sucursal y conservará 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í.
Esto depende mucho de lo que quiere decir con "revertir".
Cambiar temporalmente a un commit diferente
Si desea volver temporalmente a él, tontear, luego regresar a donde está, todo lo que tiene que hacer es revisar el compromiso deseado:
# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32
O si quieres hacer confirmaciones mientras estás allí, sigue adelante y crea una nueva sucursal mientras estás en ello:
git checkout -b old-state 0d1d7fc32
Para volver a donde estaba, solo revise la rama en la que estaba nuevamente. (Si ha realizado cambios, como siempre al cambiar de sucursal, tendrá que tratar con ellos según corresponda. Podría reiniciar para desecharlos; podría esconder, retirar y guardar para llevarlos consigo; podría cometer ellos a una rama allí si quieres una rama allí.)
Duro borrar los compromisos no publicados.
Si, por otro lado, quieres realmente deshacerte de todo lo que has hecho desde entonces, hay dos posibilidades. Una, si no ha publicado ninguno de estos compromisos, simplemente reinicie:
# 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 te equivocas, ya has desechado tus cambios locales, pero al menos puedes volver a donde estabas antes reiniciando de nuevo.
Deshacer confirmaciones publicadas con nuevas confirmaciones
Por otro lado, si ha publicado el trabajo, es probable que no desee restablecer la rama, ya que eso es efectivamente reescribir el historial. En ese caso, de hecho podrías revertir las confirmaciones. Con Git, revertir tiene un significado muy específico: crear una confirmación con el parche inverso para cancelarla. De esta manera no reescribirás ninguna historia.
# 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-revert
revert realmente 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 quería 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 nuevo a una ubicación anterior? (Cabeza separada)
Hay un comando (que no es una parte del núcleo Git, pero está en el paquete git-extras ) específicamente para revertir y organizar los confirmaciones antiguas:
git back
Por la página de manual , también se puede utilizar como tal:
# Remove the latest three commits
git back 3
He intentado muchas formas de revertir los cambios locales en Git, y parece que esto funciona mejor si solo quieres revertir al estado de confirmación más reciente.
git add . && git checkout master -f
Breve descripción:
- NO creará ninguna confirmación como lo hace
git revert
. - NO separará su HEAD como lo hace
git checkout <commithashcode>
. - Anulará todos sus cambios locales y BORRARÁ todos los archivos agregados desde la última confirmación en la rama.
- Funciona solo con los nombres de las sucursales, por lo que puede revertir solo a la última confirmación en la sucursal de esta manera.
Encontré una manera mucho más conveniente y sencilla de lograr los resultados anteriores:
git add . && git reset --hard HEAD
donde HEAD apunta a la última confirmación en su rama actual.
Es el mismo código que sugiere boulder_ruby, pero he agregado git add .
antes de git reset --hard HEAD
para borrar todos los archivos nuevos creados desde la última confirmación, ya que esto es lo que la mayoría de la gente espera, al volver a la última confirmación.
La mejor opción para mí y probablemente otras es la opción de restablecimiento 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 menciona en los comentarios, no haga esto si está compartiendo su sucursal con otras personas que tienen copias de los antiguos compromisos.
También de los comentarios, si quisieras un método menos ''tonto'' podrías usar
git clean -i
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 todos los confirmaciones se hubieran regresado. Luego, puede confirmar el árbol actual y creará un nuevo compromiso esencialmente equivalente al compromiso al que usted "revertió".
(El indicador --no-commit
permite a git revertir todas las confirmaciones a la vez; de lo contrario, se le pedirá un mensaje para cada confirmación en el rango, ensuciando su historial con nuevas confirmaciones innecesarias).
Esta es una forma segura y fácil de retroceder a un estado anterior . No se destruye ninguna historia, por lo que se puede utilizar para confirmaciones que ya se han hecho públicas.
Nada aquí me funcionó aparte de esta combinación exacta:
git reset --hard <commit_hash>
git push origin <branch_name> --force
La clave aquí es forzar la inserción, no hay mensajes adicionales de confirmación / confirmación, etc.
Para limpiar completamente el directorio de un codificador de algunos cambios accidentales, utilizamos:
git add -A .
git reset --hard HEAD
Solo git reset --hard HEAD
eliminará las modificaciones, pero no eliminará los archivos "nuevos". En su caso, accidentalmente arrastraron una carpeta importante a algún lugar, y todos esos archivos estaban siendo tratados como nuevos por Git, por lo que un reset --hard
que no se solucionó. git add -A .
el git add -A .
de antemano, los rastreó explícitamente a todos con git, para ser eliminado por el reinicio.
Para mantener los cambios del compromiso anterior a HEAD y pasar al compromiso anterior, haga:
git reset <SHA>
Si no se requieren cambios de la confirmación anterior a HEAD y simplemente descarta todos los cambios, haz:
git reset --hard <SHA>
Puede completar todos estos pasos iniciales y volver al repositorio de git.
Obtenga la última versión de su repositorio desde Bitbucket usando el comando
git pull --all
.Ejecute el comando git log con -n 4 desde su terminal. El número después de -n determina 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
Restablezca el historial del repositorio de su repositorio con
git reset --hard HEAD~N
donde N es el número de confirmaciones que desea recuperar. En el siguiente ejemplo, la cabecera se retrasaría un compromiso, al último compromiso en el historial del repositorio:Presiona el cambio a git repo usando
git push --force
para forzar el cambio.
Si quieres git repositorio a un commit anterior
git pull --all
git reset --hard HEAD~1
git push --force
Puedes hacerlo mediante los siguientes dos comandos:
git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f
Se eliminará su anterior compromiso Git.
Si desea mantener sus cambios, también puede utilizar:
git reset --soft [previous Commit SHA id here]
Entonces guardará tus cambios.
Revertir es el comando para deshacer las confirmaciones.
git revert <commit1> <commit2>
Muestra:
git revert 2h3h23233
Es capaz de tomar rango de la cabeza como abajo. Aquí 1 dice "revertir último cometer".
git revert HEAD~1..HEAD
y luego hacer git push
Seleccione su compromiso requerido, y verifíquelo por
git show HEAD
git show HEAD~1
git show HEAD~2
hasta que obtenga el compromiso requerido. Para que la CABEZA apunte a eso, haz
git reset --hard HEAD~1
o git reset --hard HEAD~2
o lo que sea.
Si desea "anular la confirmación", borre el último mensaje de confirmación y vuelva a colocar los archivos modificados en la preparación, debe usar el comando:
git reset --soft HEAD~1
-
--soft
indica que los archivos no confirmados deben conservarse como archivos de trabajo opuestos a--hard
que los descartaría. -
HEAD~1
es el último commit. Si desea deshacer 3 confirmaciones, puede usarHEAD~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/
Suponiendo que está hablando de maestro y de esa rama respectiva (dicho esto, podría ser cualquier rama de trabajo que le interese):
# Revert local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
# Revert remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master
Encontré la respuesta en la publicación del blog Eliminar el repositorio remoto de Git para un compromiso específico .
Vuelva a la confirmación más reciente e ignore todos los cambios locales:
git reset --hard HEAD
Está bien, volver a la confirmación anterior en git es bastante fácil ...
Vuelva atrás sin guardar los cambios:
git reset --hard <commit>
Vuelve atrás manteniendo los cambios:
git reset --soft <commit>
Explicar: usando git reset, puedes restablecer a un estado específico, es común usarlo con un hash de confirmación como se ve arriba.
Pero como ves, la diferencia es usar las dos banderas --soft
y --hard
, por defecto, git reset
usando --soft
flag, pero es una buena práctica usar la bandera, explico cada una de las banderas:
--suave
El indicador predeterminado tal como se explica, no es necesario que lo proporcione, no cambia el árbol de trabajo, pero agrega todos los archivos de cambios listos para confirmar, por lo que regresa al estado de confirmación que los cambios en los archivos se desestabilizan.
--difícil
¡Tenga cuidado con esta bandera, restablece el árbol de trabajo y todos los cambios a los archivos rastreados y todo desaparecerá!
También creé la siguiente imagen que puede suceder en una vida real trabajando con git:
Intenta restablecer el compromiso deseado -
git reset <COMMIT_ID>
(para verificar el uso de COMMIT_ID git log
)
Esto restablecerá todos los archivos modificados al estado sin agregar.
Ahora puedes checkout
todos los archivos sin agregar por
git checkout .
Compruebe git log
para verificar sus cambios.
ACTUALIZAR
Si tienes uno y solo cometer en tu repo, prueba
git update-ref -d HEAD
Para revertir (o revertir):
- git revert --no-commit "commit-code-to-remove" HEAD (por ejemplo, git revert --no-commit d57a39d HEAD)
- git commit
- git push
Pruebe los dos pasos anteriores, y si encuentra que esto es lo que desea, entonces git push.
Si encuentras algo mal hazlo:
git revert --abort
Como sus confirmaciones se empujan de forma remota, debe eliminarlos. Déjame asumir que tu rama está desarrollada y es empujada sobre el origen.
Primero necesitas eliminar el desarrollo desde el 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, empujar desarrollar de nuevo:
git push origin develop
Si desea corregir algún error en la última confirmación, una buena alternativa sería usar el comando git commit --amend . Si la última confirmación no se señala con ninguna referencia, esto hará el truco, ya que creará una confirmación con el mismo padre que la última confirmación. Si no hay ninguna 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 las confirmaciones sin revertir las confirmaciones. Sin embargo tiene sus propias limitaciones.
Si la situación es urgente , y solo desea hacer lo que el interlocutor le preguntó de forma rápida y sucia , suponiendo que su proyecto está en el directorio "mi proyecto":
Copie todo el directorio y llámelo otra cosa, como "mi proyecto - copiar"
Hacer:
git reset --hard [first-4-letters&numbers-of-commit''s-SHA]
Luego tiene dos versiones en su sistema ... puede examinar, 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 no iría 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 renombrar su directorio nuevamente: elimine el proyecto que contiene la confirmación recuperada (o asígnele un nombre temporal) y cambie su nombre " mi proyecto - copia "directorio de nuevo a" mi proyecto ". Entonces, probablemente haga otro compromiso bastante pronto.
Git es una creación brillante, pero no puedes simplemente "recogerlo sobre la marcha": también las personas que intentan explicarlo con demasiada frecuencia asumen el conocimiento previo de otros VCS [Sistemas de control de versiones] y profundizan demasiado profundamente demasiado pronto, y cometer otros delitos, como usar términos intercambiables para "verificar", en formas que a veces parecen casi calculadas para confundir a un principiante.
Para ahorrarte mucho estrés, tienes que leer un libro sobre Git. Recomendaría "Control de versiones con Git" . Y si puedes confiar en mí (o más bien en mis cicatrices) cuando digo "tengo que hacerlo", se deduce que también puedes hacerlo AHORA . Gran parte de la complejidad de Git proviene de la ramificación y luego de la fusión. Pero a partir de tu pregunta, no hay razón para que la gente te ciegue con la ciencia .
¡Especialmente si, por ejemplo, esta es una situación desesperada y eres un novato con Git!
PD: otro pensamiento: es (ahora) bastante simple mantener el repositorio Git ("repo") en un directorio diferente al que contiene 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 here . Sin embargo, tenga cuidado : 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 absolutamente debería. haga copias de seguridad regularmente de su repositorio, preferiblemente en la nube (por ejemplo, Google Drive ) entre otros lugares.