Git: “Objeto solto corrompido”


329

Sempre que puxo do meu controle remoto, recebo o seguinte erro sobre compactação. Quando executo a compactação manual, obtenho o mesmo:

$ git gc
error: Could not read 3813783126d41a3200b35b6681357c213352ab31
fatal: bad tree object 3813783126d41a3200b35b6681357c213352ab31
error: failed to run repack

Alguém sabe o que fazer sobre isso?

Do arquivo cat, recebo o seguinte:

$ git cat-file -t 3813783126d41a3200b35b6681357c213352ab31
error: unable to find 3813783126d41a3200b35b6681357c213352ab31
fatal: git cat-file 3813783126d41a3200b35b6681357c213352ab31: bad file

E do git fsck eu recebo isso (não sei se está realmente relacionado):

$ git fsck
error: inflate: data stream error (invalid distance too far back)
error: corrupt loose object '45ba4ceb93bc812ef20a6630bb27e9e0b33a012a'
fatal: loose object 45ba4ceb93bc812ef20a6630bb27e9e0b33a012a (stored in .git/objects/45/ba4ceb93bc812ef20a6630bb27e9e0b33a012a) is corrupted

Alguém pode me ajudar a decifrar isso?


Você já tentou examinar o último objeto (45ba4ceb93bc812ef20a6630bb27e9e0b33a012a)?
Gintautas Miliauskas

4
Obrigado ... mas como se "olha" para um objeto? Ainda novo no git :) #
asgerhallas

2
'Git show' não me dá mais do que 'git fsck' infelizmente já fez.
asgerhallas

4
Linus Torvalds escreveu o seguinte documento útil sobre esse erro e como reconstruir manualmente os blobs se você tiver os arquivos: Como recuperar um objeto de blob corrompido Alguns truques para reconstruir objetos de blob para corrigir um repositório corrompido
Uwe Kleine-König

2
Você pode adicionar alguns comentários ou editar a resposta aceita? Estou exatamente na mesma situação, e a resposta aceita não parece conter detalhes suficientes para "Just Work TM", mas, em vez disso, me forçará a mergulhar nos detalhes.
ripper234

Respostas:


57

Parece que você tem um objeto de árvore corrompido. Você precisará obter esse objeto de outra pessoa. Espero que eles tenham uma versão incorreta.

Você pode reconstruí-lo se não conseguir encontrar uma versão válida de outra pessoa, adivinhando quais arquivos devem estar lá. Você pode querer ver se as datas e horas dos objetos correspondem a ele. Essas podem ser as bolhas relacionadas. Você pode inferir a estrutura do objeto em árvore a partir desses objetos.

Dê uma olhada nos screencasts de Git de Scott Chacon sobre os internos do git. Isso mostrará como o git funciona sob o capô e como realizar esse trabalho de detetive se você estiver realmente preso e não puder obter esse objeto de outra pessoa.


2
pode ser armazenado em um arquivo de pacote. É assim que o git compacta o armazenamento de objetos armazenando deltas. Objetos soltos são aqueles que ainda não estão em um pacote. Google para arquivos de pacote, arquivos de índice no git e você poderá mergulhar na profundidade que precisar.
Adam Dymitruk

2
Você poderia fornecer um link na sua resposta para os screencasts de Chait no Git?
Ehtesh Choudhury

1
git cat-file -t <SHA1>dirá o tipo. Se não estiver corrompido, você poderá fazer isso git cat-file <type> <SHA1>para ver o conteúdo (usei-o para a blob, acho que também mostrará o conteúdo de outros tipos).
Carl G

1
Além disso, este post do Linus descreve o processo de recuperação de um blob. Quando eu segui estas instruções, porém, git statusresponsed fatal: unable to read <SHA1>mesmo que eu tinha executado com êxito git hash-object -w <file>(provavelmente porque, por suas instruções, eu tinha movido esse arquivo objeto afastado Retornando ele só me deu o mesmo. corrupt loose objectErro.)
Carl G

2
E agora repita em inglês, por favor
Mehdi

359

Eu tive o mesmo problema (não sei por que).

Essa correção requer acesso a uma cópia remota não corrompida do repositório e manterá intacta sua cópia local de trabalho.

Mas tem algumas desvantagens:

  • Você perderá o registro de quaisquer confirmações que não foram enviadas por push e terá que confirmá-las novamente.
  • Você perderá todos os esconderijos.

O conserto

Execute estes comandos no diretório pai acima do seu repositório (substitua 'foo' pelo nome da pasta do seu projeto):

  1. Crie um backup do diretório corrompido:
    cp -R foo foo-backup
  2. Faça um novo clone do repositório remoto para um novo diretório:
    git clone git@www.mydomain.de:foo foo-newclone
  3. Exclua o subdiretório .git corrompido:
    rm -rf foo/.git
  4. Mova o subdiretório .git recém-clonado para foo:
    mv foo-newclone/.git foo
  5. Exclua o restante do novo clone temporário:
    rm -rf foo-newclone

No Windows, você precisará usar:

  • copy ao invés de cp -R
  • rmdir /S ao invés de rm -rf
  • move ao invés de mv

Agora, foo tem seu .gitsubdiretório original de volta, mas todas as alterações locais ainda estão lá. git status, commit, pull, push, Etc. trabalho novamente como deveriam.


11
Este método funcionou para mim. No entanto, acredito que todas as confirmações não enviadas foram perdidas. Os dados de repo não foram tocados.
wonton

30
Sim, as informações de confirmação não enviadas serão perdidas. Porém, em cenários comuns (sem várias ramificações locais com alterações não pressionadas em outras que não as atuais), todas as modificações mais recentes do arquivo (exclusões de tinta) ainda estão em disco, portanto, é possível repetir facilmente quaisquer confirmações não pressionadas anteriores. Como eu sempre empurro após qualquer sequência de confirmações, eu ainda não tive esse problema.
alface cúbica

7
Simples e direto. Esta é a IMO, a solução mais eficiente se você não entender tudo sobre o git e não quiser mexer no seu repositório.
Oliboy50

4
Eu acho que removeria todos os stashes, pois eles são armazenados no subdiretório .git.
Anthony Elliott

4
Caso haja submódulos no projeto, é necessário iniciá-los antes de recuperar a .gitpasta.
precisa saber é o seguinte

243

Sua melhor aposta é provavelmente clonar novamente do repositório remoto (por exemplo, Github ou outro). Infelizmente, você perderá quaisquer confirmações não enviadas e alterações ocultas; no entanto, sua cópia de trabalho deve permanecer intacta.

Primeiro faça uma cópia de backup dos seus arquivos locais. Em seguida, faça isso a partir da raiz da sua árvore de trabalho:

rm -fr .git
git init
git remote add origin [your-git-remote-url]
git fetch
git reset --mixed origin/master
git branch --set-upstream-to=origin/master master  

Em seguida, confirme os arquivos alterados, conforme necessário.


12
IMHO esta deve ser a resposta aceita. Muito mais fácil do que excluir o repo e clonar novamente! :) Embora você perca quaisquer confirmações faseadas ...
Nick

6
Obviamente, se você estava em um ramo diferente do mestre quando ocorreu a corrupção, substitua masterpelo nome do seu ramo.
Timothy Zorn

Principalmente funcionou como está, mas eu estava em outro ramo workingquando ele foi corrompido e essas etapas não me deram uma cópia local de nenhum ramo workingque não fosse o mestre (e sim, eu tentei substituir o mestre acima por mas não funcionou). Acabei fazendo as etapas acima com master, em seguida, escondendo minhas alterações e fazendo checkout -b working origin/workinge aparecendo a esconderijo lá. Parece ter funcionado - obrigado!
fantabolous

1
Meu repositório tinha um submódulo que não estava corrompido. Esse processo deixou o repositório e seu submódulo em um estado em que comandos como git statuscederam fatal: Not a git repository: submodules/my-sub/../../.git/modules/my-sub. Excluir o submódulo do sistema de arquivos e reiniciar o processo restaurou a normalidade. Provavelmente, garantir que não haja conjuntos de alterações não empurrados nos submódulos primeiro é uma boa idéia ...
Steven Baldasty

5
Fiz isso hoje e não perdi alterações não confirmadas nos arquivos :) (git 2.17.1)
Fábio Dias

173

Trabalhando em uma VM, no meu notebook, a bateria acabou, recebi esse erro;

erro: arquivo de objeto .git / objects / ce / theRef está vazio erro: arquivo de objeto .git / objects / ce / theRef está vazio fatal: objeto solto theRef (armazenado em .git / objects / ce / theRef) está corrompido

Consegui fazer o repo funcionar novamente com apenas 2 comandos e sem perder meu trabalho (arquivos modificados / alterações não confirmadas)

find .git/objects/ -size 0 -exec rm -f {} \;
git fetch origin

Depois que eu executei um git status, o repositório foi bom e houve minhas alterações (aguardando confirmação, faça-o agora ..).

git versão 1.9.1

Lembre-se de fazer backup de todas as alterações que lembrar, caso essa solução não funcione e seja necessária uma abordagem mais radical.


10
find .git/objects/ -size 0 -exec rm -f {} \;trabalha para mim;)
Lazaro Fernandes Lima Suleiman

Teve o mesmo problema, executou o comando, funcionou perfeitamente para mim no Mint VM.
Ludvig Rydahl

Também funcionou perfeitamente sem ter que fazer mais nada.
Halsafar 19/06/19

1
Não em uma VM e isso funcionou para mim muitas vezes. IDK por que isso continua acontecendo no meu projeto atual, mas isso sempre o corrige.
James L.

7
Pode ser necessário executar git symbolic-ref HEAD refs/heads/master.após a exclusão dos objetos vazios.
19717 Stephan

43

Meu computador travou enquanto eu escrevia uma mensagem de confirmação. Após a reinicialização, a árvore de trabalho estava como eu a havia deixado e pude confirmar com êxito minhas alterações.

No entanto, quando tentei correr git status, consegui

error: object file .git/objects/xx/12345 is empty
fatal: loose object xx12345 (stored in .git/objects/xx/12345 is corrupt

Ao contrário da maioria das outras respostas, eu não estava tentando recuperar nenhum dado . Eu só precisava que o Git parasse de reclamar sobre o arquivo de objeto vazio.

Visão geral

O "arquivo de objeto" é a representação em hash do git de um arquivo real com o qual você se preocupa. O Git acha que deveria ter uma versão com hash some/file.whateverarmazenada .git/object/xx/12345, e corrigir o erro acabou sendo principalmente uma questão de descobrir qual arquivo o "objeto solto" deveria representar.

Detalhes

As opções possíveis pareciam ser

  1. Exclua o arquivo vazio
  2. Coloque o arquivo em um estado aceitável pelo Git

Abordagem 1: Remover o arquivo de objeto

A primeira coisa que tentei foi apenas mover o arquivo de objeto

mv .git/objects/xx/12345 ..

Isso não funcionou - o git começou a reclamar de um link quebrado. Para a abordagem 2.

Abordagem 2: corrigir o arquivo

Linus Torvalds tem um ótimo artigo sobre como recuperar um arquivo de objeto que resolveu o problema para mim. As principais etapas estão resumidas aqui.

$> # Find out which file the blob object refers to
$> git fsck
broken link from    tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
           to    blob xx12345
missing blob xx12345

$> git ls-tree 2d926
...
10064 blob xx12345  your_file.whatever

Isso informa qual arquivo o objeto vazio deve ser um hash. Agora você pode consertá-lo.

$> git hash-object -w path/to/your_file.whatever

Depois de fazer isso, verifiquei .git/objects/xx/12345, não estava mais vazio e o git parou de reclamar.


Eu estava em uma situação em que não tinha nenhum controle remoto ou backup do meu repositório e onde o objeto corrompido foi adicionado próximo ao commit inicial, provavelmente corrompendo a árvore inteira de qualquer maneira. Eu tinha o meu próprio caminho tentando recriar o objeto em um repositório diferente, mas essa resposta alcança o mesmo resultado com mais requinte.
Estecka

13

Experimentar

git stash

Isso funcionou para mim. Esconde tudo o que você não cometeu e contornou o problema.


Esquisito!?! Me deparei com este erro esta manhã. Tinha cometido ontem, por isso não foi alterado. Fez o seguinte: git stash ... fatal: Não foi possível criar ' touch .git/a / home / <user> /.git/index.lock': toque de erro de entrada / saída : não é possível tocar em '.git / a': erro de entrada / saída sudo touch /home/guest/.git/a SEM ERRO git stash Não alterações locais para salvar git status ... nada a cometer, diretório de trabalho limpo
go2null

1
@ go2null Estou um pouco atrasado nisso, mas erros de entrada / saída geralmente significam problemas no disco rígido. Embora eu tenha certeza que você já descobriu isso até agora.
precisa saber é

"Não é possível salvar o estado atual do índice"
Vladimir Brasil

9

Uma coleta de lixo corrigiu meu problema:

git gc --aggressive --prune=now

Demora um pouco para ser concluído, mas todos os objetos soltos e / ou índices corrompidos foram corrigidos.


Esta é uma boa solução. Trabalhou para mim. Meu sistema foi desligado acidentalmente. No entanto, esse comando me salvou da clonagem e de todas essas tarefas pesadas. Obrigado Jago.
Mukesh Kumar

"falha ao executar o reflog"
Vladimir Brasil

5

simplesmente executando um git pruneproblema corrigido para mim


Isso funcionou para mim e parece ser a solução mais fácil. Não sei por que essa resposta não recebeu mais votos. A única desvantagem é que a próxima git pulldemora um pouco mais do que o habitual, eu acho, porque está substituindo alguns objetos removidos ou algo assim.
steev 30/05/19

1
O motivo pode ser que o git ameixa não resolva o problema.
precisa saber é o seguinte

4

Acabei de experimentar isso - minha máquina travou enquanto escrevia no repositório Git e ficou corrompida. Corrigi-o da seguinte maneira.

Comecei analisando quantas confirmações não havia enviado ao repositório remoto, assim:

gitk &

Se você não usar esta ferramenta, é muito útil - disponível em todos os sistemas operacionais, tanto quanto eu sei. Isso indicava que meu controle remoto estava faltando dois commits. Portanto, cliquei no rótulo indicando a confirmação remota mais recente (geralmente isso será/remotes/origin/master ) para obter o hash (o hash tem 40 caracteres, mas, por uma questão de brevidade, estou usando 10 aqui - geralmente isso funciona de qualquer maneira).

Aqui está:

14c0fcc9b3

Clico no commit a seguir (ou seja, o primeiro que o controle remoto não possui) e obtenho o hash lá:

04d44c3298

Eu então uso os dois para fazer um patch para esse commit:

git diff 14c0fcc9b3 04d44c3298 > 1.patch

Em seguida, fiz o mesmo com o outro commit ausente, ou seja, usei o hash do commit anterior e o hash do próprio commit:

git diff 04d44c3298 fc1d4b0df7 > 2.patch

Depois mudei para um novo diretório, clonei o repositório do controle remoto:

git clone git@github.com:username/repo.git

Em seguida, mudei os arquivos de patch para a nova pasta e os apliquei e confirmei com suas mensagens de confirmação exatas (elas podem ser coladas git logna gitkjanela):

patch -p1 < 1.patch
git commit

patch -p1 < 2.patch
git commit

Isso restaurou as coisas para mim (e observe que provavelmente existe uma maneira mais rápida de fazer isso para um grande número de confirmações). No entanto, eu estava ansioso para ver se a árvore no repositório corrompido pode ser reparada e a resposta é que pode. Com um repositório reparado disponível como acima, execute este comando na pasta quebrada:

git fsck 

Você obterá algo como isto:

error: object file .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d is empty
error: unable to find ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d
error: sha1 mismatch ca539ed815fefdbbbfae6e8d0c0b3dbbe093390d

Para fazer o reparo, eu faria isso na pasta quebrada:

rm .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d
cp ../good-repo/.git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d .git/objects/ca/539ed815fefdbbbfae6e8d0c0b3dbbe093390d

ou seja, remova o arquivo corrompido e substitua-o por um bom. Você pode ter que fazer isso várias vezes. Finalmente, haverá um ponto em que você pode executarfsck sem erros. Você provavelmente terá as linhas "dangling commit" e "dangling blob" no relatório, que são uma consequência de suas rebotes e reparações nesta pasta e estão OK. O coletor de lixo os removerá no devido tempo.

Assim (pelo menos no meu caso) uma árvore corrompida não significa que as confirmações não enviadas sejam perdidas.


3

Eu estava recebendo um erro corrompido de objeto solto também.

./objects/x/x

Corrigi-o com sucesso, entrando no diretório do objeto corrompido. Vi que os usuários atribuídos a esse objeto não eram do meu usuário do git. Não sei como aconteceu, mas corri um chown git:gitarquivo e funcionou novamente.

Isso pode ser uma solução potencial para os problemas de algumas pessoas, mas não é necessário para todas elas.


2

Eu recebi esse erro depois que minha máquina (windows) decidiu reiniciar-se. Felizmente, meu repo remoto estava atualizado, então fiz um novo clone do Git ..



2

Eu segui muitos dos outros passos aqui; A descrição de Linus de como olhar para a árvore / objetos git e descobrir o que está faltando foi especialmente útil. git-git recuperar blob corrompido

Mas, no final, para mim, havia objetos de árvore soltos / corrompidos causados ​​por uma falha parcial do disco, e os objetos de árvore não são tão facilmente recuperados / não cobertos por esse documento.

No final, tirei o conflito objects/<ha>/<hash>do caminho e usei git unpack-objectscom um arquivo de pacote de um clone razoavelmente atualizado. Foi capaz de restaurar os objetos em árvore ausentes.

Ainda me deixou muitos blobs pendentes, o que pode ser um efeito colateral da descompactação de coisas anteriormente arquivadas e abordada em outras perguntas aqui


2

Em resposta a @ user1055643 falta o último passo:

$ rm -fr .git
$ git init
$ git remote add origin your-git-remote-url
$ git fetch
$ git reset --hard origin/master
$ git branch --set-upstream-to=origin/master master  

é --set-upstream-para um argumento válido? Acho que não!
Sharif Mamun

2
git branch (--set-upstream-para = <upstream> | -u <upstream>) [<nome da filial>]]
Ertuğrul Altınboğa

Se você remover .gite copiar do projeto clonado, o repositório funcionará, mas nenhuma ramificação local nem stashes serão preservados.
Vladimir Vukanac

1

Acabamos de ter o caso aqui. Aconteceu que o problema era que a propriedade do arquivo corrompido era raiz, em vez de nosso usuário normal. Isso foi causado por uma confirmação feita no servidor depois que alguém fez um "sudo su -".

Primeiro, identifique seu arquivo corrompido com:

$> git fsck --full

Você deve receber uma resposta como esta:

fatal: loose object 11b25a9d10b4144711bf616590e171a76a35c1f9 (stored in .git/objects/11/b25a9d10b4144711bf616590e171a76a35c1f9) is corrupt

Vá na pasta onde está o arquivo corrompido e faça um:

$> ls -la

Verifique a propriedade do arquivo corrompido. Se isso for diferente, volte para a raiz do seu repositório e faça um:

$> sudo chown -R YOURCORRECTUSER:www-data .git/

Espero que ajude!


1

Para mim, isso aconteceu devido a uma falha de energia ao fazer um git push.

As mensagens eram assim:

$ git status
error: object file .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74 is empty
error: object file .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74 is empty
fatal: loose object c238824eb3fb602edc2c49fccb535f9e53951c74 (stored in .git/objects/c2/38824eb3fb602edc2c49fccb535f9e53951c74) is corrupt

Eu tentei coisas do tipo, git fsckmas isso não ajudou. Como a falha ocorreu durante um git push, obviamente ocorreu durante a reescrita no lado do cliente, o que ocorre após a atualização do servidor. Olhei em volta e percebi que, c2388no meu caso, era um objeto de confirmação, porque era referido pelas entradas em .git/refs. Então, eu sabia que seria capaz de encontrar c2388quando olhar a história (por meio de uma interface da web ou de um segundo clone).

No segundo clone, fiz um git log -n 2 c2388para identificar o antecessor de c2388. Então eu modifiquei manualmente .git/refs/heads/mastere .git/refs/remotes/origin/masterpara ser o antecessor em c2388vez de c2388. Então eu poderia fazer a git fetch. A git fetchfalha ocorreu algumas vezes em conflitos em objetos vazios. Eu removi cada um desses objetos vazios até obter git fetchêxito. Isso curou o repositório.


1

Eu resolvi desta maneira: decidi simplesmente copiar o arquivo de objeto não corrompido do clone do backup para o meu repositório original. Isso funcionou tão bem. (A propósito: se você não conseguir encontrar o objeto em .git / objects / pelo nome, provavelmente ele foi embalado [pacote] para economizar espaço).


0

Eu tive esse mesmo problema no meu repositório remoto remoto do git. Após muita solução de problemas, descobri que um dos meus colegas de trabalho havia feito um commit no qual alguns arquivos em .git / objects tinham permissões de 440 (r - r -----) em vez de 444 (r - r - r -) Depois de pedir ao colega de trabalho para alterar as permissões com "objetos chmod 444 -R" dentro do repositório bare git, o problema foi corrigido.


0

Eu apenas tive um problema como este. Meu problema específico foi causado por uma falha no sistema que corrompeu a confirmação mais recente (e, portanto, também a ramificação principal). Eu não tinha pressionado e queria refazer esse compromisso. No meu caso particular, eu pude lidar com isso assim:

  1. Faça um backup de .git/:rsync -a .git/ git-bak/
  2. Verifique .git/logs/HEADe encontre a última linha com um ID de confirmação válido. Para mim, esse foi o segundo commit mais recente. Isso foi bom, porque eu ainda tinha as versões de diretório de trabalho do arquivo e, portanto, todas as versões que eu queria.
  3. Faça uma ramificação nesse commit: git branch temp <commit-id>
  4. refaça a confirmação quebrada com os arquivos no diretório de trabalho.
  5. git reset master temp para mover a ramificação principal para o novo commit que você fez na etapa 2.
  6. git checkout mastere verifique se está bem git log.
  7. git branch -d temp.
  8. git fsck --fulle agora deve ser seguro excluir qualquer objeto corrompido encontrado pelo fsck.
  9. Se tudo parecer bom, tente empurrar. Se isso funcionar,

Isso funcionou para mim. Suspeito que esse seja um cenário razoavelmente comum, já que o commit mais recente é o mais provável de ser corrompido, mas se você perder outro, provavelmente ainda poderá usar um método como esse, com o uso cuidadoso de git cherrypicke o reflog no .git/logs/HEAD.


0

Quando tive esse problema, fiz backup de minhas alterações recentes (como sabia o que havia mudado) e excluí o arquivo que estava reclamando em .git / location. Então eu fiz um puxão de git. Tome cuidado, porém, isso pode não funcionar para você.


0

Eu encontrei isso quando meu sistema travou. O que eu fiz é o seguinte:

(Observe que suas confirmações corrompidas foram perdidas, mas as alterações são mantidas. Talvez seja necessário recriar essas confirmações no final deste procedimento)

  • Faça backup do seu código.
  • Vá para o seu diretório de trabalho e exclua a .gitpasta.
  • Agora clone o controle remoto em outro local e copie a .gitpasta nele.
  • Cole-o no seu diretório de trabalho.
  • Confirme como você queria.

-7

Apenas remova a pasta .git e adicione-a novamente. Esta solução simples funcionou para mim.


3
Isso destruirá seu repositório local ..., pode ter efeitos colaterais bastante indesejados :) Edite sua proposta e adicione esse aviso.
Felix

1
Se você remover .gite copiar do projeto clonado, o repositório funcionará, mas nenhuma ramificação local nem stashes serão preservados. Além disso, uma sugestão amigável, exclua sua resposta completamente para parar de receber votos negativos.
Vladimir Vukanac

1
whoa nelly ... falar sobre o uso de uma bazuca para um trabalho de pinça.
Tuncay Göncüoğlu
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.