Retroceder a un antiguo compromiso de Git en un repositorio público

802

¿Cómo puedo hacer retroceder a un commit específico en git ?

La mejor respuesta que alguien me podía dar era usar git revertX veces hasta que alcanzara la confirmación deseada.

Entonces, digamos que quiero volver a una confirmación que tiene 20 confirmaciones antiguas, tendría que ejecutarla 20 veces.

¿Hay una manera más fácil para hacer esto?

No puedo usar reset porque este repositorio es público.

David
fuente
1
git revert <commitir> no funciona?
miku
8
Como dije en mi pregunta, esto realmente no me ayuda si quiero volver a algo que hace 20 commits.
David
77
Esta pregunta ha sido bastante bien respondida aquí stackoverflow.com/questions/4114095/…
user7610
44
No está claro qué quieres decir con "retroceder". ¿Eso significa que desea cambiar temporalmente su copia de trabajo a una revisión en particular? ¿O desea revertir permanentemente el historial de su repositorio a una revisión determinada?
1
Debería aceptar una respuesta, y posiblemente votar cualquier otra respuesta que desee.
Nabil Kadimi

Respuestas:

1194

Prueba esto:

git checkout [revision] .

donde [revision]está el hash commit (por ejemplo:) 12345678901234567890123456789012345678ab.

No olvides .al final, muy importante. Esto aplicará cambios a todo el árbol. Debe ejecutar este comando en la raíz del proyecto git. Si está en un subdirectorio, entonces este comando solo cambia los archivos en el directorio actual. Entonces comprométete y deberías ser bueno.

Puedes deshacer esto por

git reset --hard 

eso eliminará todas las modificaciones del directorio de trabajo y el área de preparación.

Alex Reisner
fuente
77
@AlexReisner Ese período en los puntos finales del directorio en el que se encuentra actualmente, que no es necesariamente todo el proyecto git, ¿correcto? Si quisiera aplicar los cambios a todo el proyecto, ¿utilizaría ': /' como en 'git add: /', si no estuviera actualmente en la raíz del proyecto git?
MSpreij
10
nota: si ha agregado nuevos archivos a su proyecto desde entonces, esto no los eliminará. Entonces, cuando vaya a compilar (dependiendo de su plataforma), es posible que aún obtenga errores. Elimina los archivos nuevos y listo.
TheWestIsThe ...
66
@MSpreij Debe ejecutar este comando en la raíz del proyecto git. Si está en un subdirectorio, entonces este comando solo cambia los archivos en el directorio actual.
volatilevar
3
Es genial cuando puedes clonar un proyecto en otro directorio y usar git checkout [revisión]. para volver a una revisión específica y luego compararla con el mismo proyecto en otro directorio. Ahorra un montón de tiempo.
Donato
44
Maldición, olvidé el "." ¿Qué daño he hecho a mi repositorio?
Owl
196

Para revertir a una confirmación específica:

git reset --hard commit_sha

Para revertir 10 confirmaciones:

git reset --hard HEAD~10

Puede usar "git revert" como en la siguiente publicación si no desea reescribir el historial

¿Cómo revertir el repositorio de Git a una confirmación previa?

Naga Kiran
fuente
44
única diferencia entre este enfoque y "git checkout [revisión]". es que este último conserva las revisiones.
deeshank
53
Esta respuesta es INCORRECTA ya que OP dice específicamente "No puedo usar reset porque este repositorio es público"
Yarin
44
Si el repositorio es público, creo que no hay forma de revertir la confirmación en el repositorio público sin usar force push (git push -f) ya que afectará a las personas que han introducido los cambios antes de la reversión. Por lo tanto, reset también se puede usar en el sandbox local de un repositorio público.
Naga Kiran
44
¡Es genial que esto evite una CABEZA separada! Justo lo que estaba buscando.
cyber-monk
1
En mi caso, esto funcionó, luego use 'git pull' para avanzar rápidamente de regreso a la cabeza después de haber probado las regresiones, etc.
Peter Quiring el
86

Bueno, supongo que la pregunta es, ¿qué quieres decir con 'retroceder'? Si no puede resetporque es público y desea mantener intacto el historial de confirmación, ¿quiere decir que solo quiere que su copia de trabajo refleje una confirmación específica? Use git checkouty el hash commit.

Editar: como se señaló en los comentarios, el uso git checkoutsin especificar una rama lo dejará en un estado "sin rama". Se usa git checkout <commit> -b <branchname>para pagar en una rama o git checkout <commit> .para pagar en la rama actual.

Ben
fuente
¿No te pone esto en el extraño estado 'Actualmente no en ninguna sucursal'? ¿Cómo se comprometen los cambios para completar la reversión?
Alex Reisner el
Bueno, solo estoy sugiriendo el uso de git checkout: es libre de visitar cualquier sucursal (actual o nueva) que desee. Actualizaré mi respuesta para que no sea ambigua.
Ben
2
Intenté esto, pero no creo que esta sea la forma correcta de hacerlo porque deja archivos estancados. Esto no elimina los archivos que no estaban en esa última confirmación.
David
3
Si está en un directorio de trabajo y permanece en el maestro, debe git reseteliminar esos archivos, lo que dice que no desea hacer. Intenta hacerlo en una rama separada: git checkout <commit> -b <branchname>no tendrás archivos estancados en esa rama .
Ben
2
El problema con el uso checkoutes que no eliminará los archivos que se agregaron en una confirmación anterior.
42

El cartel original dice:

La mejor respuesta que alguien me podía dar era usar git revertX veces hasta que alcanzara la confirmación deseada.

Entonces, digamos que quiero volver a una confirmación que tiene 20 confirmaciones antiguas, tendría que ejecutarla 20 veces.

¿Hay una manera más fácil para hacer esto?

No puedo usar reset porque este repositorio es público.

No es necesario usar git revertX veces. git revertpuede aceptar un rango de confirmación como argumento, por lo que solo necesita usarlo una vez para revertir un rango de confirmaciones. Por ejemplo, si desea revertir las últimas 20 confirmaciones:

git revert --no-edit HEAD~20..

El rango de confirmación HEAD~20..es corto HEAD~20..HEADy significa "comenzar desde el vigésimo padre de la confirmación HEAD, y revertir todas las confirmaciones hasta HEAD".

Eso revertirá los últimos 20 commits, suponiendo que ninguno de ellos sea commit de fusión. Si hay confirmaciones de fusión, entonces no puede revertirlas todas en un solo comando, deberá revertirlas individualmente con

git revert -m 1 <merge-commit>

Tenga en cuenta también que he probado usando un rango con el git revertuso de git versión 1.9.0. Si está utilizando una versión anterior de git, utilizar un rango con git revertmayo o mayo no funciona.

En este caso, git revertse prefiere sobre git checkout.

Tenga en cuenta que, a diferencia de esta respuesta que dice usargit checkout , en git revert realidad eliminará todos los archivos que se agregaron en cualquiera de las confirmaciones que está revocando , lo que hace que esta sea la forma correcta de revertir un rango de revisiones.

Documentación

cañón de riel
fuente
Nota : esto crea una nueva confirmación con los cambios revertidos. Perfecto para la pregunta de OP. Pero asegúrate de que eso es lo que quieres. (Los ejemplos en el git- revert vinculado anteriormente son excelentes). Si en su lugar desea investigar los compromisos anteriores (es decir, antes de elegir qué compromiso volver), utilice la opción de pago mencionada en otras respuestas, teniendo en cuenta los comentarios que otros tienen hecho sobre archivos borrados.
SherylHohman
@SherylHohman Volver a una confirmación anterior no crea una nueva confirmación. No puedo imaginar lo que quieres decir aquí.
27

Paso 1: buscar la lista de confirmaciones:

git log

Obtendrá una lista como en este ejemplo:

[Comp:Folder User$ git log
commit 54b11d42e12dc6e9f070a8b5095a4492216d5320
Author: author <[email protected]>
Date:   Fri Jul 8 23:42:22 2016 +0300

This is last commit message

commit fd6cb176297acca4dbc69d15d6b7f78a2463482f
Author: author <[email protected]>
Date:   Fri Jun 24 20:20:24 2016 +0300

This is previous commit message

commit ab0de062136da650ffc27cfb57febac8efb84b8d
Author: author <[email protected]>
Date:   Thu Jun 23 00:41:55 2016 +0300

This is previous previous commit message
...

Paso 2: copie el hash de confirmación necesario y péguelo para pagar:

git checkout fd6cb176297acca4dbc69d15d6b7f78a2463482f

Eso es todo.

Igor
fuente
11
git read-tree -um @ $commit_to_revert_to

lo haré. Es "git checkout" pero sin actualizar HEAD.

Puedes lograr el mismo efecto con

git checkout $commit_to_revert_to
git reset --soft @{1}

si prefiere encadenar comandos de conveniencia juntos.

Estos lo dejan con su árbol de trabajo e índice en el estado deseado, puede git committerminar.

jthill
fuente
¡Este es el único enfoque directo que funcionó de maravilla! Revisé desde la cabeza, ejecuté este comando, y eliminó con éxito los archivos agregados que habíamos introducido y revirtió todos los cambios. Excelente.
kamranicus
6

¿Quieres el modo HEAD separado?

Si desea revertir el tiempo X a una determinada confirmación con una CABEZA DETACHADA (lo que significa que no puede estropear nada), entonces, por supuesto, use lo siguiente:

(reemplace X con la cantidad de confirmaciones que desea volver)

git checkout HEAD~X

IE para retroceder una confirmación:

git checkout HEAD~1
Karl Morrison
fuente
1
Quitaría la parte con ... difícil de creer ... Parece personal, y también alguien lo mencionó en un comentario anterior, y también en @ken en su respuesta.
meJustAndrew
@meJustAndrew Es, tantas respuestas sobre SO que confunden a la gente, es bastante molesto.
Karl Morrison
Qué respuesta tan simple y directa.
Ammad
2

Digamos que trabajas en un proyecto y después de un día más o menos. Observa que una característica aún le está dando errores. Pero no sabe qué cambio realizó que causó el error. Por lo tanto, debe pescar los compromisos de trabajo anteriores. Para volver a una confirmación específica:

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 .

Ok, entonces ese commit funciona para ti. No más errores. Usted identificó el problema. Ahora puede volver a la última confirmación:

git checkout 792d9294f652d753514dc2033a04d742decb82a5 .

Y revise un archivo específico antes de que cause el error (en mi caso, uso el ejemplo Gemfile.lock):

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 -- /projects/myproject/Gemfile.lock

Y esta es una forma de manejar los errores que creó en commits sin darse cuenta de los errores hasta más tarde.

Donato
fuente
2

Puede encontrar la identificación de confirmación relacionada con cada confirmación en la sección de confirmaciones de GitHub / BitBucket / Gitlab. Es muy simple, suponga que su ID de confirmación es 5889575, luego, si desea volver a esta parte en su código, simplemente necesita escribir

git checkout 5889575 .

Esto lo llevará a ese punto de tiempo en su código.

Ahmad Naved
fuente
1

No estoy seguro de qué cambió, pero no puedo pagar una confirmación específica sin la opción --detach . El comando completo que funcionó para mí fue: git checkout --detach [commit hash]

Para regresar del estado separado, tuve que revisar mi sucursal local: git checkout master

conocer
fuente
La salida masterresuelve el problema de permanecer separado, mientras trabajaba git reset --hardo git checkout -- .trabajó pero permaneció separado
DarkCygnus
0

Aquí hay un ejemplo para hacer eso

    cd /yourprojects/project-acme 


    git checkout efc11170c78 .
mcvkr
fuente