Encontrar e restaurar um arquivo excluído em um repositório Git

Digamos I'm em um repositório Git. Eu apago um arquivo e submeto essa alteração. Eu continuo trabalhando e faço mais alguns commits. Então, acho que preciso restaurar esse arquivo.

Eu sei que posso fazer checkout de um arquivo usando git checkout HEAD^ foo.bar, mas eu não'não sei realmente quando esse arquivo foi apagado.

  1. Qual seria a maneira mais rápida de encontrar o commit que apagou um determinado nome de arquivo?
  2. Qual seria a maneira mais fácil de colocar o arquivo de volta na minha cópia de trabalho?

I'espero não ter que navegar manualmente pelos meus logs, fazer checkout de todo o projecto para um determinado SHA e depois copiar manualmente esse ficheiro para o meu checkout original do projecto.

Solução

Encontre o último compromisso que afetou o caminho dado. Como o ficheiro não está no HEAD commit, este commit deve tê-lo apagado.


git rev-list -n 1 HEAD -- 
Comentários (20)
  1. Utilize git log --diff-filter=D --summary para obter todos os commits que apagaram ficheiros e os ficheiros apagados;
  2. Utilize git checkout $commit~1 path/to/file.ext para restaurar o ficheiro apagado.

Onde $commit é o valor do commit que você encontrou no passo 1, por exemplo e4cf499627.

Comentários (11)

Se você estiver louco, use git-bisect. Aqui está o que fazer:

git bisect start
git bisect bad
git bisect good 

Agora é hora de fazer o teste automático. O comando shell '[ -e foo.bar ]' retornará 0 se foo.bar existir, e 1 caso contrário. O comando "run" do git-bisect utilizará a busca binária para encontrar automaticamente o primeiro commit onde o teste falhar. Ele inicia pela metade do intervalo dado (de bom para ruim) e o corta pela metade com base no resultado do teste especificado.

git bisect run '[ -e foo.bar ]'

Agora estás no compromisso que o apagou. Daqui, você pode pular de volta para o futuro e usar git-revert para desfazer a mudança,

git bisect reset
git revert 

ou você poderia voltar atrás e inspecionar manualmente os danos:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .
Comentários (4)