Como recuperar o repositório git quebrado / parcialmente excluído

7

Eu corri acidentalmente um rm -r no meu diretório .git. Felizmente rm parou quando chegou a um arquivo protegido contra gravação, mas eu ainda perdi várias coisas no meu .git.

Arquivos que ainda tenho:

FETCH_HEAD
ORIG_HEAD
config
gitk.cache
logs/
objects/

Arquivos que perdi:

HEAD
description
hooks/
index
info/
packed-refs
refs/

Pelo que posso dizer, as únicas coisas que perdi e não consegui clonar novamente são as alterações na minha área de teste e minhas referências. Estou preparado para perder minhas mudanças de estágio, mas preciso recuperar minha CABEÇA e minhas filiais. Existe uma maneira de fazer isso? Diga, encontrando commits que não têm filhos, verificando-os para ver o que eles são e criando ramificações para eles? No momento, o git nem mesmo reconhece meu repositório como repositório.

    
por Shum 05.03.2013 / 04:32

1 resposta

11

Todos os commits e arquivos que eles referenciariam seriam armazenados como objetos no diretório objects . O Git cria esses como somente leitura, então eles devem ainda estar presente.

Para recuperar, aconselho a criação de um novo repositório vazio e a cópia do conteúdo do diretório objects do seu repositório quebrado para o do novo 1. Isso deve levá-lo a um ponto em que o git reconhecerá pelo menos é um repositório e terá todos os seus objetos. Trabalhando com uma cópia também ajudará a evitar causar mais danos ao tentar consertar as coisas.

Comandos do shell para criar o repositório temporário e copiar os objetos:

git init /tmp/recovery
cd /tmp/recovery
cp -r /path/to/broken/repo/.git/objects .git

Uma vez feito isso, você pode usar git fsck para obter uma lista de objetos que não são referenciados por nada. Isso deve incluir todos os chefes de filiais, mas também incluiria quaisquer commits que foram tornados obsoletos por git commit --amend ou pelo rebase.

Como você ainda tem o diretório de logs que provavelmente será ainda maior Socorro. Deve haver um arquivo logs/refs/heads/<branch> para cada ramificação que você tinha. A segunda coluna da última linha conterá o ID do commit que estava na cabeceira daquele ramo quando a exclusão foi feita. Deveria também ser logs/HEAD com a mesma informação para onde o HEAD estava, mas a menos que você estivesse trabalhando com uma cabeça isolada é provavelmente melhor apenas recuperar os ramos e, em seguida, fazer o checkout de um branch normalmente.

Para cada ramo que você deseja restaurar, você pode executar:

git branch <name> <commit_id>

Uma vez que você tenha restaurado as ramificações você pode copiar sobre o arquivo de configuração, e você deve estar bem perto de onde você estava desde o último commit.

    
por 05.03.2013 / 05:30