Como recuperar objetos Git danificados por falha no disco rígido?
-
03-07-2019 - |
Pergunta
Eu tive uma falha no disco rígido que resultou em alguns arquivos de um repositório Git ficar danificado. Ao executar git fsck --full
eu recebo o seguinte resultado:
error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch
error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid code lengths set)
error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid stored block lengths)
error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack
fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted
Eu tenho backups do repositório, mas o único backup que inclui o arquivo do pacote tem já danificado. Então eu acho que eu tenho que descobrir uma maneira de recuperar os objetos individuais de backups diferentes e de alguma forma Instrua Git para produzir um novo pacote com apenas objetos corretos.
Você pode por favor me dê sugestões como corrigir meu repositório?
Solução
Em alguns backups anteriores, seus objetos ruins pode ter sido embalada em arquivos diferentes ou podem ser objetos soltos ainda. Assim, os objetos podem ser recuperados.
Parece que há alguns objetos ruins em sua base de dados. Então, você poderia fazê-lo da maneira manual.
Por causa de git hash-object
, git mktree
e git commit-tree
não escrever os objetos porque eles são encontrados no pacote, em seguida, começar a fazer isso:
mv .git/objects/pack/* <somewhere>
for i in <somewhere>/*.pack; do
git unpack-objects -r < $i
done
rm <somewhere>/*
(Seus pacotes são movidos para fora do repositório, e descompactado novamente nele, só os bons objetos estão agora no banco de dados)
Você pode fazer:
git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee
e verificar o tipo do objeto.
Se o tipo é blob:. Recuperar o conteúdo do arquivo a partir de backups anteriores (com git show
ou git cat-file
ou git unpack-file
; então você pode git hash-object -w
para reescrever o objeto em seu repositório atual
Se o tipo é uma árvore: você poderia usar git ls-tree
para recuperar a árvore de backups anteriores; em seguida, git mktree
para escrevê-lo novamente em seu repositório atual.
Se o tipo é cometer:. O mesmo com git show
, git cat-file
e git commit-tree
Claro, eu faria um backup sua cópia de trabalho original antes de iniciar este processo.
Além disso, dê uma olhada em Como recuperar corrompido Blob objeto .
Outras dicas
Banengusk estava me colocando no caminho certo. Para mais referência, eu quero postar os passos que tomou para corrigir o meu corrupção repositório. Eu estava bastante sorte de encontrar todos os objetos necessários, quer em embalagens mais velhos ou em backups do repositório.
# Unpack last non-corrupted pack
$ mv .git/objects/pack .git/objects/pack.old
$ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack
$ git log
fatal: bad object HEAD
$ cat .git/HEAD
ref: refs/heads/master
$ ls .git/refs/heads/
$ cat .git/packed-refs
# pack-refs with: peeled
aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master
$ git fsck --full
error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1
error: refs/heads/master does not point to a valid object!
missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919
missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b
dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc
# Copy HEAD object from backup of repository
$ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa
# Now copy all missing objects from backup of repository and run "git fsck --full" afterwards
# Repeat until git fsck --full only reports dangling objects
# Now garbage collect repo
$ git gc
warning: reflog of 'HEAD' references pruned commits
warning: reflog of 'refs/heads/master' references pruned commits
Counting objects: 3992, done.
Delta compression using 2 threads.
fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232)
error: failed to run repack
# Check reflogs...
$ git reflog
# ...then clean
$ git reflog expire --expire=0 --all
# Now garbage collect again
$ git gc
Counting objects: 3992, done.
Delta compression using 2 threads.
Compressing objects: 100% (3970/3970), done.
Writing objects: 100% (3992/3992), done.
Total 3992 (delta 2060), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.
# Done!
Tente os seguintes comandos no primeiro (re-executar novamente, se necessário):
$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase
E então você ainda tem os problemas, tente pode:
-
remover todos os objetos corruptos, por exemplo.
fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt $ rm -v .git/objects/06/91c5...51e5
-
remover todos os objetos vazios, por exemplo.
error: object file .git/objects/06/91c5...51e5 is empty $ find .git/objects/ -size 0 -exec rm -vf "{}" \;
-
verificar a relação da mensagem "quebrado" por:
git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
Esta vontade diz-lhe o arquivo do blob corrupto veio!
-
para recuperar arquivo, você pode ser muita sorte, e pode ser a versão que você já fez check-out na sua árvore de trabalho:
git hash-object -w my-magic-file
novamente, e se mostrar o SHA1 falta (4b945 ..) você está agora tudo feito!
-
assumindo que era uma versão mais antiga que foi quebrado, a maneira mais fácil de fazer isso é fazer:
git log --raw --all --full-history -- subdirectory/my-magic-file
e que irá mostrar-lhe todo o log para esse arquivo (por favor, perceber que a árvore que você teve não pode ser a árvore de nível superior, então você precisa descobrir qual subdiretório foi em em seu próprio país), então você pode agora recriar o objeto falta com hash objeto novamente.
-
para obter uma lista de todas as refs com falta comete, árvores ou blobs:
$ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
Pode não ser possível remover alguns desses refs usando o -d ramo regular ou comandos -d tag, uma vez que eles vão morrer se git percebe a corrupção. Portanto, use o git update-ref comando encanamento -d $ ref em vez. Note-se que em caso de agências locais, este comando pode deixar de configuração ramo obsoleto trás em .git / config. Ele pode ser excluído manualmente (olhar para o [ramo "$ ref"] seção).
-
Depois de todos refs são limpos, há ainda pode ser quebrado commits na reflog. Você pode limpar todos os reflogs usando git reflog expirar --expire = agora --all. Se você não quer perder todos os seus reflogs, você pode procurar os juízes individuais para reflogs quebrados:
$ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
(Note a opção -g adicionado ao rev-list git.) Em seguida, use git reflog expirar --expire = agora $ ref em cada um deles. Quando todas as refs quebrados e reflogs se foram, executar git fsck --full, a fim de verificar se o repositório é limpo. objetos pendurados são Ok.
Abaixo, você pode encontrar o uso avançado de comandos que potencialmente pode causar perda de seus dados em seu repositório git se não for usado com sabedoria, então faça um backup antes de você acidentalmente fazer mais danos ao seu git. Tente em seu próprio risco se você sabe o que está fazendo.
Para puxar o ramo atual no topo do ramo a montante depois de baixá:
$ git pull --rebase
Você também pode tentar fazer check-out novo ramo e apagar o antigo:
$ git checkout -b new_master origin/master
Para encontrar o objeto corrompido no git para remoção, tente o seguinte comando:
while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done
Para OSX, o uso sed -E
vez de sed -r
.
Outra idéia é para descompactar todos os objetos de arquivos do pacote para regenerar todos os objetos dentro .git / objetos, de modo a tentar executar os seguintes comandos dentro de seu repositório:
$ cp -fr .git/objects/pack .git/objects/pack.bak
$ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
$ rm -frv .git/objects/pack.bak
Se acima não ajudar, você pode tentar rsync ou copiar os objetos do git de outro repo, por exemplo.
$ rsync -varu git_server:/path/to/git/.git local_git_repo/
$ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
$ cp -frv ../other_repo/.git/objects .git/objects
Para corrigir o ramo quebrado ao tentar check-out da seguinte forma:
$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625
Tente removê-lo e check-out de montante novamente:
$ git branch -D master
$ git checkout -b master github/master
No caso git você entrar em estado destacado, o checkout da master
e fundir-se que o ramo separado.
Outra idéia é rebase do mestre existente de forma recursiva:
$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master
Veja também:
- Alguns truques para reconstruir blob objetos, a fim de corrigir um repositório corrompido.
- Como corrigir um repositório quebrado?
- Como remover todas as refs quebrados a partir de um repositório?
- como corrigir corrompido repositório git? (Seeques)
- Como corrigir repositório git corrompido? (Qnundrum)
- erro ao usar SourceTree com Git: 'Resumo' falhou com o código 128: fatal: incapaz de ler árvore
- Recuperar A Corrupt Git nua Repository
- recuperar um git repositório danificado
- Como corrigir erro de git: objeto é empy / corrupto
- Como diagnosticar e corrigir git fatal : incapaz de ler árvore
- Como lidar com esse erro git
- como corrigir corrompido repositório git?
- Como eu 'sobrescrever ', em vez de 'fusão', uma filial em outro ramo na Git?
- Como substituir branch master no git , inteiramente, de outro ramo?
- Git: "Corrupt objeto solto"
- git reset = fatal: incapaz de ler árvore
Aqui estão os passos que eu segui para recuperar um objeto blob corrupto.
1) Identificar blob corrupto
git fsck --full
error: inflate: data stream error (incorrect data check)
error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd
error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing
...
Corrupt blob é 241091723c324aed77b2d35f97a05e856b319efd
2) Mova blob corrupto para um lugar seguro (apenas no caso)
mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/
3) Obter pai de blob corrupto
git fsck --full
Checking object directories: 100% (256/256), done.
Checking objects: 100% (70321/70321), done.
broken link from tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
to blob 241091723c324aed77b2d35f97a05e856b319efd
haxixe Pai é 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180 .
4) Obter nome do ficheiro correspondente ao blob corrupto
git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
...
100644 blob 241091723c324aed77b2d35f97a05e856b319efd dump.tar.gz
...
Ver este arquivo específico em um backup ou no repositório git a montante (no meu caso é dump.tar.gz ). Em seguida, copie-o em algum lugar dentro do seu repositório local.
5) Adicionar arquivo previamente corrompido no banco de dados git objeto
git hash-object -w dump.tar.gz
6) Celebrate!
git gc
Counting objects: 75197, done.
Compressing objects: 100% (21805/21805), done.
Writing objects: 100% (75197/75197), done.
Total 75197 (delta 52999), reused 69857 (delta 49296)
git checkout pode realmente escolher arquivos individuais a partir de uma revisão. Basta dar-lhe o hash e o nome do arquivo cometer. informações mais detalhadas aqui.
Eu acho que a maneira mais fácil de corrigir isso com segurança é reverter para o backup mais recente uncommited e, em seguida, seletivamente escolher arquivos não corrompidos de commits mais recentes. Boa sorte!
Aqui são duas funções que podem ajudar se o backup está corrompido, ou você tem alguns backups parcialmente danificados, bem como (isso pode acontecer se você faça backup os objectos corrompidos).
Executar tanto no repo que você está tentando recuperar.
aviso padrão: use apenas se você está realmente desesperada e você fez backup de seu repo (corrompido). Isto pode não resolve nada, mas pelo menos deve destacar o nível de corrupção.
fsck_rm_corrupted() {
corrupted='a'
while [ "$corrupted" ]; do
corrupted=$( \
git fsck --full --no-dangling 2>&1 >/dev/null \
| grep 'stored in' \
| sed -r 's:.*(\.git/.*)\).*:\1:' \
)
echo "$corrupted"
rm -f "$corrupted"
done
}
if [ -z "$1" ] || [ ! -d "$1" ]; then
echo "'$1' is not a directory. Please provide the directory of the git repo"
exit 1
fi
pushd "$1" >/dev/null
fsck_rm_corrupted
popd >/dev/null
e
unpack_rm_corrupted() {
corrupted='a'
while [ "$corrupted" ]; do
corrupted=$( \
git unpack-objects -r < "$1" 2>&1 >/dev/null \
| grep 'stored in' \
| sed -r 's:.*(\.git/.*)\).*:\1:' \
)
echo "$corrupted"
rm -f "$corrupted"
done
}
if [ -z "$1" ] || [ ! -d "$1" ]; then
echo "'$1' is not a directory. Please provide the directory of the git repo"
exit 1
fi
for p in $1/objects/pack/pack-*.pack; do
echo "$p"
unpack_rm_corrupted "$p"
done
Eu resolvi este problema adicionar alguma mudança como -A add git e git commit novamente.