Git: "Objeto suelto corrupto"


329

Cada vez que saco de mi control remoto, aparece el siguiente error sobre la compresión. Cuando ejecuto la compresión manual, obtengo lo mismo:

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

¿Alguien sabe qué hacer al respecto?

De cat-file obtengo esto:

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

Y de git fsck obtengo esto (no sé si realmente está 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

¿Alguien puede ayudarme a descifrar esto?


¿Has intentado mirar el último objeto (45ba4ceb93bc812ef20a6630bb27e9e0b33a012a)?
Gintautas Miliauskas

44
Gracias ... pero ¿cómo se "mira" un objeto? Todavía nuevo en git :)
asgerhallas

2
´git show´ no me da nada más que ´git fsck´ que lamentablemente ya lo hizo
asgerhallas

44
Linus Torvalds escribió el siguiente documento útil sobre este error y cómo reconstruir manualmente los blobs si tiene los archivos: Cómo recuperar un objeto blob dañado Algunos trucos para reconstruir objetos blob para reparar un repositorio dañado
Uwe Kleine-König

2
¿Puedes agregar algunos comentarios o editar la respuesta aceptada? Estoy exactamente en la misma situación, y la respuesta aceptada no parece contener suficientes detalles para "Just Work TM", sino que me obliga a sumergirme en los detalles yo mismo.
ripper234

Respuestas:


57

Parece que tienes un objeto de árbol corrupto. Deberá obtener ese objeto de otra persona. Esperemos que tengan una versión incorrupta.

En realidad, podría reconstruirlo si no puede encontrar una versión válida de otra persona adivinando qué archivos deberían estar allí. Es posible que desee ver si las fechas y horas de los objetos coinciden. Esos podrían ser los blobs relacionados. Podría inferir la estructura del objeto del árbol a partir de esos objetos.

Echa un vistazo a las transmisiones de pantalla de Git de Scott Chacon sobre las partes internas de git. Esto le mostrará cómo funciona git debajo del capó y cómo hacer este trabajo de detective si realmente está atrapado y no puede obtener ese objeto de otra persona.


2
se puede almacenar en un archivo de paquete. Esta es la forma en que git comprime el almacenamiento de objetos almacenando deltas. Los objetos sueltos son aquellos que aún no están en un paquete. Google para los archivos de paquete, indexe los archivos en git y debería poder sumergirse tan profundo como lo necesite.
Adam Dymitruk

2
¿Podría proporcionar un enlace en su respuesta a los screencasts de Chacon's Git?
Ehtesh Choudhury

1
git cat-file -t <SHA1>te dirá el tipo. Si no está dañado, puede hacerlo git cat-file <type> <SHA1>para ver el contenido (lo usé para un blob, supongo que también le mostrará el contenido de otros tipos).
Carl G

1
También esta publicación de Linus describe el proceso para recuperar a blob. Cuando he seguido estas instrucciones, sin embargo, git statusresponsed fatal: unable to read <SHA1>pesar de que había corrió con éxito git hash-object -w <file>(probablemente porque, según sus instrucciones, me había trasladado ese archivo objeto de distancia Volviendo simplemente me dio la misma. corrupt loose objectError.)
Carl G

2
Y ahora repite en inglés por favor
Mehdi

359

Tuve el mismo problema (no sé por qué).

Esta solución requiere acceso a una copia remota no corrupta del repositorio y mantendrá intacta su copia de trabajo local.

Pero tiene algunos inconvenientes:

  • Perderá el registro de cualquier confirmación que no se haya enviado y tendrá que volver a comprometerla.
  • Perderás cualquier alijo.

La solución

Ejecute estos comandos desde el directorio principal sobre su repositorio (reemplace 'foo' con el nombre de su carpeta de proyecto):

  1. Cree una copia de seguridad del directorio corrupto:
    cp -R foo foo-backup
  2. Realice un nuevo clon del repositorio remoto en un nuevo directorio:
    git clone git@www.mydomain.de:foo foo-newclone
  3. Eliminar el subdirectorio corrupto .git:
    rm -rf foo/.git
  4. Mueva el subdirectorio .git recién clonado a foo:
    mv foo-newclone/.git foo
  5. Elimine el resto del nuevo clon temporal:
    rm -rf foo-newclone

En Windows deberá usar:

  • copy en vez de cp -R
  • rmdir /S en vez de rm -rf
  • move en vez de mv

Ahora foo tiene su .gitsubdirectorio original , pero todos los cambios locales siguen ahí. git status, commit, pull, push, Etc trabajo de nuevo como deberían.


11
Este método funcionó para mi. Sin embargo, creo que todos los compromisos no deseados se perdieron. Los datos del repositorio no se han modificado.
wonton

30
Sí, la información de confirmación no solicitada se perderá. Pero en escenarios comunes (no hay múltiples sucursales locales con cambios no acelerados en otros que no sean el actual), todas las modificaciones de archivos más recientes (eliminaciones inkl.) Todavía están en el disco, por lo tanto, uno puede repetir fácilmente cualquier confirmación no acelerada anterior. Como siempre presiono después de cualquier secuencia de confirmaciones, incluso no me encontré con este problema.
lechuga cúbica

77
Simple y directo. Esta es, IMO, la solución más eficiente si no entiende todo sobre git y no quiere jugar con su repositorio.
Oliboy50

44
Creo que eliminaría todos los escondites ya que están almacenados en el subdirectorio .git.
Anthony Elliott

44
En caso de que haya submódulos en el proyecto, es necesario iniciarlos antes de recuperar la .gitcarpeta.
AdrieanKhisbe

243

Su mejor opción es probablemente volver a clonar desde el repositorio remoto (es decir, Github u otro). Desafortunadamente, perderá cualquier confirmación no apurada y cambios escondidos, sin embargo, su copia de trabajo debe permanecer intacta.

Primero haga una copia de seguridad de sus archivos locales. Luego haga esto desde la raíz de su árbol de trabajo:

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  

Luego, confirme los archivos modificados según sea necesario.


12
En mi humilde opinión, esta debería ser la respuesta aceptada. ¡Mucho más fácil que eliminar el repositorio y volver a clonar! :) A pesar de que pierdes cualquier commit organizado ...
Nick

66
Obviamente, si estaba en una rama distinta de la maestra cuando ocurrió la corrupción, reemplácela mastercon el nombre de su rama.
Timothy Zorn

La mayoría de las veces funcionó tal como está, pero estaba en otra rama workingcuando se corrompió y estos pasos no me dieron una copia local de ninguna rama que no sea la maestra (y sí, intenté reemplazar la maestra anterior workingpero eso no funcionó). Terminé haciendo los pasos anteriores con master, luego escondiendo mis cambios y haciendo checkout -b working origin/workingy sacando el alijo allí. Parece haber funcionado, ¡gracias!
fantabolous

1
Mi repositorio tenía un submódulo que no estaba dañado. Este proceso dejó el repositorio y su submódulo en un estado donde los comandos como git statuscedieron fatal: Not a git repository: submodules/my-sub/../../.git/modules/my-sub. Eliminar el submódulo del sistema de archivos y reiniciar el proceso restableció la normalidad. Probablemente asegurarse de que no haya conjuntos de cambios sin empujar en los submódulos primero es una buena idea ...
Steven Baldasty

55
Hice esto hoy y no perdí cambios no comprometidos en los archivos :) (git 2.17.1)
Fábio Dias

173

Trabajando en una VM, en mi computadora portátil, la batería se agotó, recibí este error;

error: el archivo de objeto .git / objects / ce / theRef está vacío error: el archivo de objeto .git / objects / ce / theRef está vacío fatal: objeto suelto theRef (almacenado en .git / objects / ce / theRef) está dañado

Logré que el repositorio funcione nuevamente con solo 2 comandos y sin perder mi trabajo (archivos modificados / cambios no confirmados)

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

Después de eso ejecuté un git status, el repositorio estaba bien y había mis cambios (esperando ser confirmado, hágalo ahora ...).

git versión 1.9.1

Recuerde hacer una copia de seguridad de todos los cambios que recuerde, en caso de que esta solución no funcione y se necesite un enfoque más radical.


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

Tuve el mismo problema, ejecuté el comando, funcionó perfectamente para mí en Mint VM.
Ludvig Rydahl

También funcionó perfecto sin tener que hacer nada más.
Halsafar

1
No en una máquina virtual y esto me ha funcionado muchas veces. IDK por qué esto sigue sucediendo en mi proyecto actual, pero esto lo soluciona todo el tiempo.
James L.

77
Es posible que deba ejecutar git symbolic-ref HEAD refs/heads/master.después de eliminar los objetos vacíos.
Stephan

43

Mi computadora se bloqueó mientras escribía un mensaje de confirmación. Después de reiniciar, el árbol de trabajo estaba como lo había dejado y pude confirmar con éxito mis cambios.

Sin embargo, cuando traté de correr git statusconseguí

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

A diferencia de la mayoría de las otras respuestas, no estaba tratando de recuperar ningún dato . Solo necesitaba que Git dejara de quejarse del archivo de objeto vacío.

Visión general

El "archivo objeto" es la representación hash de git de un archivo real que le interesa. Git piensa que debería tener una versión hash some/file.whateveralmacenada .git/object/xx/12345, y corregir el error resultó ser principalmente una cuestión de averiguar qué archivo se suponía que representaba el "objeto suelto".

Detalles

Las posibles opciones parecían ser

  1. Eliminar el archivo vacío
  2. Lleve el archivo a un estado aceptable para Git

Enfoque 1: eliminar el archivo objeto

Lo primero que intenté fue mover el archivo objeto

mv .git/objects/xx/12345 ..

Eso no funcionó: Git comenzó a quejarse de un enlace roto. En el enfoque 2.

Enfoque 2: arreglar el archivo

Linus Torvalds tiene una excelente descripción de cómo recuperar un archivo de objeto que resolvió el problema para mí. Los pasos clave se resumen aquí.

$> # 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

Esto le dice de qué archivo se supone que el objeto vacío es un hash. Ahora puedes repararlo.

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

Después de hacer esto, lo comprobé .git/objects/xx/12345, ya no estaba vacío, y git dejó de quejarse.


Estaba en una situación en la que no tenía ningún control remoto o copia de seguridad de mi repositorio, y donde el objeto dañado se agregó cerca de la confirmación inicial, probablemente corrompiendo todo el árbol de todos modos. Tenía mi propia manera de tratar de recrear el objeto en un repositorio diferente, pero esta respuesta logra el mismo resultado con más delicadeza.
Estecka

13

Tratar

git stash

Esto funcionó para mí. Guarda todo lo que no ha cometido y que solucionó el problema.


¡¿¡Extraño!?! Encontré este error esta mañana. Se había comprometido ayer, por lo que no ha cambiado sin compromiso. Hizo lo siguiente: git stash ... fatal: no se puede crear '/ home / <usuario> /.git/index.lock': error de entrada / salida touch .git/a táctil: no se puede tocar '.git / a': error de entrada / salida sudo touch /home/guest/.git/a NO ERROR git stash No los cambios locales para ahorrar git status ... nada de cometer, el directorio de trabajo limpia
go2null

1
@ go2null Llego un poco tarde, pero los errores de entrada / salida generalmente significan problemas con el disco duro. Aunque estoy seguro de que ya has descubierto esto.
arleslie

"No se puede guardar el estado del índice actual"
Vladimir Brasil

9

Una recolección de basura solucionó mi problema:

git gc --aggressive --prune=now

Tarda un tiempo en completarse, pero se corrigió cada objeto suelto y / o índice dañado.


Esta es una buena solución. Trabajó para mi. Mi sistema se apagó accidentalmente. Sin embargo, este comando me salvó de la clonación y de todas esas tareas pesadas. Gracias Jago
Mukesh Kumar

"no se pudo ejecutar el registro"
Vladimir Brasil

5

simplemente ejecutando un git pruneproblema solucionado para mí


Esto funcionó para mí y parece ser la solución más fácil. No estoy seguro de por qué esta respuesta no obtuvo más votos. El único inconveniente es que el siguiente git pulltarda un poco más de lo habitual, supongo porque está reemplazando algunos objetos eliminados o algo así.
steev

1
La razón podría ser que git prune no resuelve el problema en absoluto.
user3072843

4

Acabo de experimentar esto: mi máquina se bloqueó al escribir en el repositorio de Git, y se corrompió. Lo arreglé de la siguiente manera.

Comencé mirando cuántas confirmaciones no había enviado al repositorio remoto, por lo tanto:

gitk &

Si no utiliza esta herramienta, es muy útil, por lo que sé, está disponible en todos los sistemas operativos. Esto indicaba que a mi control remoto le faltaban dos confirmaciones. Por lo tanto, hice clic en la etiqueta que indica la última confirmación remota (por lo general, esto será/remotes/origin/master ) para obtener el hash (el hash tiene 40 caracteres de largo, pero por brevedad estoy usando 10 aquí, esto generalmente funciona de todos modos).

Aquí está:

14c0fcc9b3

Luego hago clic en el siguiente commit (es decir, el primero que el control remoto no tiene) y obtengo el hash allí:

04d44c3298

Luego uso ambos para hacer un parche para esta confirmación:

git diff 14c0fcc9b3 04d44c3298 > 1.patch

Luego hice lo mismo con el otro commit faltante, es decir, usé el hash del commit antes y el hash del commit en sí:

git diff 04d44c3298 fc1d4b0df7 > 2.patch

Luego me mudé a un nuevo directorio, cloné el repositorio desde el control remoto:

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

Luego moví los archivos de parche a la nueva carpeta, los apliqué y los confirmé con sus mensajes de confirmación exactos (se pueden pegar desde git logo desde la gitkventana):

patch -p1 < 1.patch
git commit

patch -p1 < 2.patch
git commit

Esto restauró las cosas para mí (y tenga en cuenta que probablemente haya una forma más rápida de hacerlo para una gran cantidad de confirmaciones). Sin embargo, estaba ansioso por ver si el árbol en el repositorio corrupto puede repararse, y la respuesta es que sí. Con un repositorio reparado disponible como el anterior, ejecute este comando en la carpeta rota:

git fsck 

Obtendrás algo como esto:

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

Para hacer la reparación, haría esto en la carpeta rota:

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

es decir, elimine el archivo dañado y reemplácelo por uno bueno. Tu debes hacer esto varias veces. Finalmente habrá un punto donde puedes correrfsck sin errores. Probablemente tendrá líneas de "compromiso pendiente" y "blob colgante" en el informe, estas son una consecuencia de sus rebases y enmiendas en esta carpeta, y están bien. El recolector de basura los eliminará a su debido tiempo.

Por lo tanto (al menos en mi caso) un árbol dañado no significa que se pierdan las confirmaciones no apresuradas.


3

También recibí un error de objeto suelto corrupto.

./objects/x/x

Lo arreglé con éxito yendo al directorio del objeto corrupto. Vi que los usuarios asignados a ese objeto no eran los usuarios de mi git. No sé cómo sucedió, pero ejecuté un chown git:gitarchivo en ese archivo y luego funcionó nuevamente.

Esto puede ser una solución potencial para los problemas de algunas personas, pero no necesariamente todos.


2

Recibí este error después de que mi máquina (Windows) decidió reiniciarse. Afortunadamente, mi repositorio remoto estaba actualizado, así que hice un nuevo git-clone ...



2

Seguí muchos de los otros pasos aquí; La descripción de Linus de cómo mirar el árbol / objetos git y encontrar lo que falta fue especialmente útil. git-git recupera la burbuja corrupta

Pero al final, para mí, tuve objetos de árbol sueltos / corruptos causados ​​por una falla parcial del disco, y los objetos de árbol no son tan fáciles de recuperar / no cubiertos por ese documento.

Al final, eliminé el conflicto objects/<ha>/<hash>y lo usé git unpack-objectscon un archivo de paquete de un clon razonablemente actualizado. Pudo restaurar los objetos del árbol que faltaban.

Todavía me dejó con muchos blobs colgantes, lo que puede ser un efecto secundario de desempacar cosas previamente archivadas, y abordado en otras preguntas aquí


2

En respuesta a @ user1055643 falta el último paso:

$ 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  

¿Es --set-upstream-a un argumento válido? ¡No lo creo!
Sharif Mamun

2
git branch (--set-upstream-to = <upstream> | -u <upstream>) [<nombre de rama>]
Ertuğrul Altınboğa

Si elimina .gity copia del proyecto clonado, el repositorio funcionará, pero no se conservarán sucursales locales ni escondites.
Vladimir Vukanac

1

Acabamos de tener el caso aquí. Sucedió que el problema era que la propiedad del archivo dañado era root en lugar de nuestro usuario normal. Esto fue causado por una confirmación realizada en el servidor después de que alguien haya realizado un "sudo su -".

Primero, identifique su archivo corrupto con:

$> git fsck --full

Debería recibir una respuesta como esta:

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

Vaya a la carpeta donde está el archivo corrupto y haga un:

$> ls -la

Verifique la propiedad del archivo corrupto. Si eso es diferente, simplemente regrese a la raíz de su repositorio y haga un:

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

¡Espero eso ayude!


1

Para mí esto ocurrió debido a un fallo de alimentación mientras se hace una git push.

Los mensajes se veían así:

$ 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

Intenté cosas como git fsckpero eso no ayudó. Dado que el bloqueo ocurrió durante un git push, obviamente sucedió durante la reescritura en el lado del cliente que ocurre después de que se actualiza el servidor. Miré a mi alrededor y pensé que c2388en mi caso era un objeto de confirmación, porque se hacía referencia a él mediante entradas en .git/refs. Entonces supe que podría encontrarlo c2388cuando mire el historial (a través de una interfaz web o un segundo clon).

En el segundo clon hice un git log -n 2 c2388para identificar al predecesor c2388. Luego lo modifiqué manualmente .git/refs/heads/mastery .git/refs/remotes/origin/masterpara ser el predecesor en c2388lugar de c2388. Entonces podría hacer un git fetch. El git fetchfallaron un par de veces para los conflictos en los objetos vacíos. Eliminé cada uno de estos objetos vacíos hasta que tuve git fetchéxito. Eso ha curado el repositorio.


1

Resolví de esta manera: decidí simplemente copiar el archivo de objeto no dañado del clon de la copia de seguridad a mi repositorio original. Esto funcionó igual de bien. (Por cierto: si no puede encontrar el objeto en .git / objects / por su nombre, probablemente haya sido [empaquetado] [paquete] para ahorrar espacio).


0

Tuve este mismo problema en mi repositorio de git remoto. Después de mucha solución de problemas, descubrí que uno de mis compañeros de trabajo había realizado una confirmación en la que algunos archivos en .git / objects tenían permisos de 440 (r - r -----) en lugar de 444 (r - r - r -). Después de pedirle al compañero de trabajo que cambiara los permisos con "objetos chmod 444 -R" dentro del repositorio de git, el problema se solucionó.


0

Acabo de tener un problema como este. Mi problema particular fue causado por un bloqueo del sistema que corrompió la confirmación más reciente (y, por lo tanto, también la rama maestra). No había presionado, y quería volver a hacer ese compromiso. En mi caso particular, pude tratarlo así:

  1. Haga una copia de seguridad de .git/:rsync -a .git/ git-bak/
  2. Verifique .git/logs/HEADy encuentre la última línea con una ID de confirmación válida. Para mí, esta fue la segunda confirmación más reciente. Esto fue bueno, porque todavía tenía las versiones de directorio de trabajo del archivo, y por lo tanto todas las versiones que quería.
  3. Haz una rama en ese commit: git branch temp <commit-id>
  4. Vuelva a hacer el commit roto con los archivos en el directorio de trabajo.
  5. git reset master temp para mover la rama maestra a la nueva confirmación que realizó en el paso 2.
  6. git checkout mastery compruebe que se ve bien con git log.
  7. git branch -d temp.
  8. git fsck --full, y ahora debería ser seguro eliminar cualquier objeto dañado que fsck encuentre.
  9. Si todo se ve bien, intenta empujar. Si eso funciona,

Eso funcionó para mí. Sospecho que este es un escenario razonablemente común, ya que el commit más reciente es el más probable que se corrompa, pero si pierde uno más atrás, es probable que aún pueda usar un método como este, con un uso cuidadoso git cherrypicky el registro en .git/logs/HEAD.


0

Cuando tuve este problema, hice una copia de seguridad de mis cambios recientes (ya que sabía lo que había cambiado) y luego eliminé el archivo del que se quejaba en .git / location. Entonces hice un git pull. Sin embargo, tenga cuidado, esto podría no funcionar para usted.


0

Encontré esto una vez que mi sistema se bloqueó. Lo que hice es esto:

(Tenga en cuenta que sus confirmaciones corruptas se pierden, pero los cambios se retienen. Es posible que tenga que volver a crear esas confirmaciones al final de este procedimiento)

  • Copia de seguridad de su código.
  • Vaya a su directorio de trabajo y elimine la .gitcarpeta.
  • Ahora clone el control remoto en otra ubicación y copie la .gitcarpeta en él.
  • Pégalo en tu directorio de trabajo.
  • Comprométete como quisieras.

-7

Simplemente elimine la carpeta .git y agréguela nuevamente. Esta solución simple funcionó para mí.


3
Esto afectará su repositorio local ..., podría tener efectos secundarios no deseados :) Edite su propuesta y agregue esa advertencia.
Felix

1
Si elimina .gity copia del proyecto clonado, el repositorio funcionará, pero no se conservarán sucursales locales ni escondites. Además, una sugerencia amigable, elimine su respuesta por completo para dejar de recibir votos negativos.
Vladimir Vukanac

1
Whoa nelly ... habla sobre el uso de una bazuca para un trabajo de pinzas.
Tuncay Göncüoğlu
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.