Como reverter um "git rm -r."?

378

Eu disse acidentalmente git rm -r .. Como me recupero disso?

Eu não cometi.

Acho que todos os arquivos foram marcados para exclusão e também foram fisicamente removidos do meu checkout local.

EDIT: eu poderia (se soubesse o comando) reverter para o último commit. Mas seria muito melhor se eu pudesse desfazer o git rm -r .. Porque não tenho muita certeza do que fiz após o último commit e antes do git rm -r ..

user89021
fonte
3
Para esta pergunta em particular, redefinir --hard é uma boa solução ... já está listada, então vou mencionar neste comentário que você pode verificar a documentação do git-reflog.
precisa saber é o seguinte
8
Observe que, como você não forneceu -fao git rmgit, não removerá nenhum arquivo que tenha sido alterado ou não em etapas, portanto, você git reset; git checkout .deve recuperar tudo.
CB Bailey
Apenas cuidado - git checkout. apagará todas as alterações não-estágios.
PeterB
11
Eu apenas fiz algo assim, e eu não entendo por que meus arquivos locais onde apagados (e, como o OP, eu não cometi ainda.)
Xonatron
Com Git 2.23+ (agosto de 2019), você iria restaurar arquivos com git restore: git restore -s@ -SW -- .. Veja minha resposta abaixo .
VonC 7/11

Respostas:

468
git reset HEAD

Deveria fazê-lo. Se você não tiver alterações não confirmadas com as quais se preocupa,

git reset --hard HEAD

deve redefinir tudo à força para seu último commit. Se você tiver alterações não confirmadas, mas o primeiro comando não funcionar, salve as alterações não confirmadas com git stash:

git stash
git reset --hard HEAD
git stash pop
Brian Campbell
fonte
22
Observe que git reset --hard HEADdestrói quaisquer alterações úteis feitas nos diretórios pai do diretório de trabalho atual.
Alex
10
@ Leve: Eu ainda estou suando frio!
hoi polloi
6
Não votei, mas tentei esconder, redefinir com força, pop e perdi todas as minhas alterações recentes. Talvez eu tenha interpretado mal a resposta.
Greg M. Krsak
11
Isso raramente funciona para mim, e estou tão feliz por trabalhar em uma pasta do Dropbox. Pobre forma, mas me salva sempre ...
Nuby 13/03
3
Quando eu git stash pop, ele apenas removeu os arquivos novamente, é claro, porque oculta o fato de eu (acidentalmente) remover alguns arquivos. Esta resposta não funcionará se você tiver alterações não confirmadas que deseja manter.
Sudo #
252

Git-rm'd alguns arquivos e continuei fazendo alterações antes do meu próximo commit quando percebi que precisava de alguns desses arquivos de volta. Em vez de esconder e redefinir, você pode simplesmente fazer o checkout dos arquivos individuais que você perdeu / removeu, se desejar:

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

Isso deixa intactas outras alterações não confirmadas, sem soluções alternativas.

Jaime Bellmyer
fonte
6
Isso ajudou porque eu tive outras alterações não confirmadas.
Dan
4
Essa resposta ajuda aqueles que se depararam com essa questão, procurando reverter uma única git rme não uma recursiva inteira git rm -r. Para uma exclusão recursiva completa, as outras soluções podem ser melhores, dependendo da quantidade de arquivos removidos.
tresf
Você, meu homem, merece um prêmio.
Salamit 27/03
Se eu pudesse clicar 100 vezes !!!
Wagner Braga
57

Para recuperar alguns arquivos ou pastas, pode-se usar o seguinte

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

Isso primeiro recriará as entradas de índice path/to/filee recriará o arquivo como estava na última confirmação, ou seja HEAD.

Dica: pode-se passar um hash de confirmação para os dois comandos para recriar arquivos de uma confirmação mais antiga. Veja git reset --helpe git checkout --helppara detalhes.

Arne L.
fonte
Melhor resposta. Fácil desfazer cirúrgico de uma única git rmoperação sem eliminar outras alterações não confirmadas.
wberry 8/07/19
Me ajudou a sair! melhor resposta.
Akram
28

Atualizar:

Como git rm .exclui todos os arquivos neste e nos diretórios filho, no checkout de trabalho e no índice, você precisa desfazer cada uma dessas alterações:

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

Isso deve fazer o que você quiser. Não afeta as pastas pai do seu código ou índice de saída.


Resposta antiga que não era:

reset HEAD

fará o truque e não apagará nenhuma alteração não confirmada que você tenha feito nos seus arquivos.

depois disso, você precisa repetir todos os git addcomandos que você colocou na fila.

Alex Brown
fonte
11
desculpe, eu sempre configuro git alias.co="checkout"para que git cofaça o checkout.
Alex Brown
25

Se você não executar nenhuma das opções acima, poderá recuperar dados usando a sugestão aqui: http://www.spinics.net/lists/git/msg62499.html

git prune -n
git cat-file -p <blob #>
Skippy VonDrake
fonte
4 anos depois, ainda salva-vidas!
ThievingSix
Eu escrevi um programa em c ++ para concatenar os resultados (eu tinha cerca de 100 objetos pendurados no meu repositório, tornando isso necessário). Apenas compile e execute, depois passe no diretório local do git repo. raw.githubusercontent.com/bluuman/git-recover-files/master/...
James Meas
15

desfazer git rm

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

desfazer git rm -r

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

desfazer git rm -rf

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

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

song xu
fonte
Obviamente, nada pode desfazer git rm -rf, pois isso também pode excluir arquivos não rastreados ou faseados (apenas).
jpaugh
git rm -rf filee git rm -rf dirnão excluirá nenhum arquivo não rastreado.
song xu
10

Se você tiver confirmado e enviado as alterações, poderá fazer isso para recuperar o arquivo

// Replace 2 with the # of commits back before the file was deleted.
git checkout HEAD~2 path/to/file
Cory Danielson
fonte
Isso funcionou para 'Alterações a serem confirmadas:', onde um arquivo foi excluído de um antigo git cherry-pick que eu ainda precisava.
mushcraft
7

Já existem boas respostas, mas posso sugerir uma sintaxe pouco usada que não só funciona muito bem, mas é muito explícita no que você deseja (portanto, não é assustador nem misterioso)

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

Obter confirmação da lista

git log  --oneline

Por exemplo, Stable commit hash: 45ff319c360cd7bd5442c0fbbe14202d20ccdf81

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

Eu tive uma situação idêntica. No meu caso, a solução foi:

git checkout -- .
Artur
fonte
0

Com o Git 2.23+ (agosto de 2019), o comando apropriado para restaurar arquivos (e o índice) seria usar ... git restore(não reset --hardou o comando confusogit checkout )

Isso é:

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

Ou sua forma abreviada:

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

Eu tinha exatamente o mesmo problema: estava limpando minhas pastas, reorganizando e movendo arquivos. Entrei: git rm . e aperte enter; e então senti minhas entranhas se soltarem um pouco. Felizmente, eu não digitei o git commit -m "" imediatamente.

No entanto, o seguinte comando

git checkout .

restaurou tudo e salvou minha vida.

Wai-Ming Lee
fonte