¿Cómo revertir un "git rm -r"?

378

Dije accidentalmente git rm -r .. ¿Cómo me recupero de esto?

No me comprometí.

Creo que todos los archivos se marcaron para su eliminación y también se eliminaron físicamente de mi pago local.

EDITAR: podría (si supiera el comando) volver al último commit. Pero sería mucho mejor si pudiera deshacer el git rm -r .. Porque no estoy realmente seguro de lo que hice después del último commit y antes del git rm -r ..

user89021
fuente
3
Para esta pregunta en particular, restablecer --hard es una buena solución ... ya está en la lista, así que solo mencionaré en este comentario que es posible que desee consultar la documentación de git-reflog.
William Pursell
8
Tenga en cuenta que debido a que no suministró -fa git rmgit, no habrá eliminado ningún archivo que tuviera cambios organizados o no organizados, por lo que git reset; git checkout .debería recuperar todo.
CB Bailey
Solo ten cuidado, git checkout. eliminará todos los cambios no organizados.
PeterB
1
Acabo de hacer algo como esto, y no entiendo por qué mis archivos locales se eliminaron (y, como el OP, todavía no me he comprometido).
Xonatron
Con Git 2.23+ (agosto de 2019), que le restaurar archivos con git restore: git restore -s@ -SW -- .. Vea mi respuesta a continuación .
VonC

Respuestas:

468
git reset HEAD

Deberías hacerlo. Si no tiene ningún cambio no comprometido que le interese, entonces

git reset --hard HEAD

debería restablecer por la fuerza todo a su último commit. Si tiene cambios no confirmados, pero el primer comando no funciona, guarde los cambios no confirmados con git stash:

git stash
git reset --hard HEAD
git stash pop
Brian Campbell
fuente
22
Tenga en cuenta que git reset --hard HEADdestruye cualquier cambio útil que haya realizado en los directorios principales del directorio de trabajo actual.
Alex Brown
10
@Mild: ¡Todavía estoy sudando frío!
hoipolloi
66
No rechacé la votación, pero solo intenté guardar, restablecer duro, explotar y perdí todos mis cambios recientes. Quizás leí mal la respuesta.
Greg M. Krsak
1
Esto rara vez funciona para mí, y estoy muy contento de trabajar en una carpeta de Dropbox. Mala forma, pero me salva cada vez ...
Nuby
3
Cuando hice git stash pop, simplemente eliminé los archivos nuevamente, por supuesto porque oculta el hecho de que (accidentalmente) eliminé algunos archivos. Esta respuesta no funciona si tiene cambios no confirmados que desea conservar.
sudo
252

Git-rmd algunos archivos y seguí haciendo cambios antes de mi próxima confirmación cuando me di cuenta de que necesitaba recuperar algunos de esos archivos. En lugar de esconder y restablecer, simplemente puede retirar los archivos individuales que perdió / eliminó si desea:

git checkout HEAD path/to/file path/to/another_file

Esto deja sus otros cambios no confirmados intactos sin soluciones.

Jaime Bellmyer
fuente
66
Esto ayudó porque tuve otros cambios no comprometidos.
Dan
44
Esta respuesta ayuda a aquellos de nosotros que tropezamos con esta pregunta buscando revertir una git rmrecursiva en lugar de una recursiva completa git rm -r. Para una eliminación recursiva completa, las otras soluciones pueden ser mejores, dependiendo de la cantidad de archivos eliminados.
Tresf
Tú, mi hombre, mereces un premio.
Salamit
¡Si pudiera, lo haría clic 100 veces!
Wagner Braga
57

Para recuperar algunos archivos o carpetas individuales, se puede usar lo siguiente

git reset -- path/to/file
git checkout -- path/to/file

Esto recreará primero las entradas de índice path/to/filey recreará el archivo como estaba en el último commit, es decir HEAD.

Sugerencia: se puede pasar un hash de confirmación a ambos comandos para recrear archivos de una confirmación anterior. Ver git reset --helpy git checkout --helppara más detalles.

Arne L.
fuente
La mejor respuesta. Fácil 'deshacer' quirúrgico de una sola git rmoperación sin eliminar otros cambios no comprometidos.
wberry
Me ayudó a salir! la mejor respuesta.
Akram
28

Actualizar:

Dado que git rm .elimina todos los archivos en este y los directorios secundarios en la comprobación de trabajo y en el índice, debe deshacer cada uno de estos cambios:

git reset HEAD . # This undoes the index changes
git checkout .   # This checks out files in this and child directories from the HEAD

Esto debería hacer lo que quieras. No afecta a las carpetas principales de su código o índice desprotegido.


Antigua respuesta que no era:

reset HEAD

hará el truco y no borrará los cambios no confirmados que haya realizado en sus archivos.

después de eso, debe repetir cualquier git addcomando que haya puesto en cola.

Alex Brown
fuente
1
lo siento, siempre configuro git alias.co="checkout"para que se git cohaga el pago.
Alex Brown
25

Si no funciona ninguno de los anteriores, puede recuperar datos utilizando la sugerencia de aquí: http://www.spinics.net/lists/git/msg62499.html

git prune -n
git cat-file -p <blob #>
Skippy VonDrake
fuente
¡4 años después, todavía es un salvavidas!
ThievingSix
Escribí un programa de c ++ para concatenar los resultados (tenía unos 100 objetos colgando en mi repositorio, lo que lo hizo necesario). Simplemente compile y ejecute, luego pase su directorio local git repo. raw.githubusercontent.com/bluuman/git-recover-files/master/…
James Meas
15

deshacer git rm

git rm file             # delete file & update index
git checkout HEAD file  # restore file & index from HEAD

deshacer git rm -r

git rm -r dir          # delete tracked files in dir & update index
git checkout HEAD dir  # restore file & index from HEAD

deshacer git rm -rf

git rm -r dir          # delete tracked files & delete uncommitted changes
not possible           # `uncommitted changes` can not be restored.

Uncommitted changesincluye not staged changes, staged changes but not committed.

canción xu
fuente
Por supuesto, nada puede deshacerse git rm -rf, ya que eso también puede eliminar archivos no rastreados o montados (solo).
jpaugh
git rm -rf filey git rm -rf dirno eliminará ningún archivo sin seguimiento.
canción xu
10

Si ha confirmado y enviado los cambios, puede hacer esto para recuperar el archivo

// Replace 2 with the # of commits back before the file was deleted.
git checkout HEAD~2 path/to/file
Cory Danielson
fuente
Esto funcionó para 'Cambios que se deben confirmar': donde se eliminó un archivo de un viejo git cherry-pick que todavía necesitaba. Intenté git reset HEAD ~ <number> <file> que no funcionó.
Mushcraft
7

Ya hay algunas buenas respuestas, pero podría sugerir una sintaxis poco utilizada que no solo funciona muy bien, sino que es muy explícita en lo que desea (por lo tanto, no da miedo ni es misterioso)

git checkout <branch>@{"20 minutes ago"} <filename>
mehtunguh
fuente
3

Obtener lista de compromiso

git log  --oneline

Por ejemplo, commit estable tiene hash: 45ff319c360cd7bd5442c0fbbe14202d20ccdf81

git reset --hard 45ff319c360cd7bd5442c0fbbe14202d20ccdf81
git push -ff origin master
Do Nhu Vy
fuente
1

Tuve una situación idéntica. En mi caso la solución fue:

git checkout -- .
Artur
fuente
0

Con Git 2.23+ (agosto de 2019), el comando adecuado para restaurar archivos (y el índice) debería ser usar ... git restore(no reset --hardo el comando confusogit checkout )

Es decir:

git restore -s=HEAD --staged --worktree -- .

O su forma abreviada:

git restore -s@ -SW -- .
VonC
fuente
-1

Tuve exactamente el mismo problema: estaba limpiando mis carpetas, reorganizando y moviendo archivos. Entré: git rm . y pulsa enter; y luego sentí que mis intestinos se aflojaban un poco. Afortunadamente, no escribí git commit -m "" inmediatamente.

Sin embargo, el siguiente comando

git checkout .

restauró todo y me salvó la vida.

Wai-Ming Lee
fuente