¿Cómo recuperar objetos Git dañados por falla del disco duro?

Resuelto Christian asked hace 15 años • 8 respuestas

Tuve una falla en el disco duro que provocó que algunos archivos de un repositorio de Git se dañaran. Al ejecutarlo git fsck --fullobtengo el siguiente 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

Tengo copias de seguridad del repositorio, pero la única copia de seguridad que incluye el archivo del paquete ya lo tiene dañado. Así que creo que tengo que encontrar una manera de recuperar los objetos individuales de diferentes copias de seguridad y de alguna manera indicarle a Git que produzca un nuevo paquete con solo los objetos correctos.

¿Puede darme sugerencias sobre cómo arreglar mi repositorio?

Christian avatar Apr 29 '09 16:04 Christian
Aceptado

En algunas copias de seguridad anteriores, es posible que los objetos defectuosos se hayan empaquetado en archivos diferentes o que aún estén sueltos. Para que sus objetos puedan ser recuperados.

Parece que hay algunos objetos defectuosos en su base de datos. Entonces podrías hacerlo de forma manual.

Debido a y git hash-objectno escribas los objetos porque se encuentran en el paquete, entonces comienza a hacer esto:git mktreegit commit-tree

mv .git/objects/pack/* <somewhere>
for i in <somewhere>/*.pack; do
  git unpack-objects -r < $i
done
rm <somewhere>/*

(Sus paquetes se sacan del repositorio y se descomprimen nuevamente en él; ahora solo los objetos buenos están en la base de datos)

Tu puedes hacer:

git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

y comprobar el tipo de objeto.

Si el tipo es blob: recupere el contenido del archivo de copias de seguridad anteriores (con git showo git cat-fileo git unpack-file; luego podrá git hash-object -wreescribir el objeto en su repositorio actual.

Si el tipo es árbol: podrías utilizarlo git ls-treepara recuperar el árbol de copias de seguridad anteriores; luego git mktreeescribirlo nuevamente en su repositorio actual.

Si el tipo es commit: lo mismo git showcon git cat-filey git commit-tree.

Por supuesto, haría una copia de seguridad de su copia de trabajo original antes de comenzar este proceso.

Además, consulte Cómo recuperar un objeto Blob dañado .

Daniel Fanjul avatar Apr 29 '2009 13:04 Daniel Fanjul

Banengusk me estaba poniendo en el camino correcto. Para mayor referencia, quiero publicar los pasos que tomé para arreglar la corrupción de mi repositorio. Tuve la suerte de encontrar todos los objetos necesarios, ya sea en paquetes más antiguos o en copias de seguridad del repositorio.

# 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!
Christian avatar May 04 '2009 13:05 Christian

Pruebe los siguientes comandos al principio (vuélvalos a ejecutar si es necesario):

$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase

Y si todavía tienes problemas, intenta:

  • eliminar todos los objetos corruptos, por ejemplo

    fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
    $ rm -v .git/objects/06/91c5...51e5
    
  • eliminar todos los objetos vacíos, por ejemplo

    error: object file .git/objects/06/91c5...51e5 is empty
    $ find .git/objects/ -size 0 -exec rm -vf "{}" \;
    
  • verifique un mensaje de "enlace roto" de la siguiente manera:

    git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
    

    ¡Esto le indicará de qué archivo proviene el blob corrupto!

  • Para recuperar el archivo, puede que tengas mucha suerte y puede que sea la versión que ya tienes en tu árbol de trabajo:

    git hash-object -w my-magic-file
    

    nuevamente, y si genera el SHA1 que falta (4b945...), ¡ya está todo listo!

  • suponiendo que se trataba de alguna versión anterior que estaba rota, la forma más sencilla de hacerlo es hacer:

    git log --raw --all --full-history -- subdirectory/my-magic-file
    

    y eso le mostrará el registro completo de ese archivo (tenga en cuenta que el árbol que tenía puede no ser el árbol de nivel superior, por lo que debe averiguar en qué subdirectorio estaba por su cuenta), luego ahora puede recrear el objeto faltante con objeto hash nuevamente.

  • para obtener una lista de todas las referencias a las que les faltan confirmaciones, árboles o blobs:

    $ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
    

    Puede que no sea posible eliminar algunas de esas referencias usando los comandos habituales de rama -d o etiqueta -d, ya que morirán si git nota la corrupción. Entonces use el comando de plomería git update-ref -d $ref en su lugar. Tenga en cuenta que en el caso de sucursales locales, este comando puede dejar una configuración de sucursal obsoleta en .git/config. Se puede eliminar manualmente (busque la sección [branch "$ref"]).

  • Después de que todas las referencias estén limpias, es posible que todavía haya confirmaciones rotas en el registro. Puede borrar todos los registros usando git reflog expire --expire=now --all. Si no desea perder todos sus registros, puede buscar en las referencias individuales registros rotos:

    $ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
    

    (Tenga en cuenta la opción -g agregada a git rev-list). Luego, use git reflog expire --expire=now $ref en cada uno de ellos. Cuando desaparezcan todas las referencias y registros rotos, ejecute git fsck --full para verificar que el repositorio esté limpio. Los objetos colgantes están bien.


A continuación puede encontrar el uso avanzado de comandos que potencialmente pueden causar la pérdida de sus datos en su repositorio de git si no se usan sabiamente, así que haga una copia de seguridad antes de que accidentalmente cause más daños a su git. Pruébalo bajo tu propia responsabilidad si sabes lo que estás haciendo.


Para colocar la rama actual encima de la rama ascendente después de recuperarla:

$ git pull --rebase

También puedes intentar verificar la nueva rama y eliminar la anterior:

$ git checkout -b new_master origin/master

Para encontrar el objeto dañado en git y eliminarlo, intente el siguiente 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, utilice sed -Een lugar de sed -r.


Otra idea es descomprimir todos los objetos de los archivos del paquete para regenerar todos los objetos dentro de .git/objects, así que intente ejecutar los siguientes comandos dentro de su repositorio:

$ 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

Si lo anterior no ayuda, puede intentar sincronizar o copiar los objetos git de otro repositorio, por ejemplo

$ 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 arreglar la rama rota al intentar pagar de la siguiente manera:

$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625

Intente eliminarlo y vuelva a realizar el pago desde arriba:

$ git branch -D master
$ git checkout -b master github/master

En caso de que git lo lleve al estado separado, consulte mastery fusione la rama separada.


Otra idea es cambiar la base del maestro existente de forma recursiva:

$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master

Ver también:

  • Algunos trucos para reconstruir objetos blob con el fin de reparar un repositorio dañado.
  • ¿Cómo arreglar un repositorio roto?
  • ¿Cómo eliminar todas las referencias rotas de un repositorio?
  • ¿Cómo reparar el repositorio git dañado? (busca)
  • ¿Cómo reparar el repositorio git dañado? (enigma)
  • Error al usar SourceTree con Git: 'Resumen' falló con el código 128: fatal: no se puede leer el árbol
  • Recuperar un repositorio básico de Git corrupto
  • Recuperar un repositorio git dañado
  • Cómo solucionar el error de git: el objeto está vacío/corrupto
  • Cómo diagnosticar y reparar git fatal: no se puede leer el árbol
  • Cómo lidiar con este error de git
  • ¿Cómo reparar el repositorio git dañado?
  • ¿Cómo puedo 'sobrescribir', en lugar de 'fusionar', una rama en otra rama en Git?
  • ¿Cómo reemplazar la rama master en git, por completo, desde otra rama?
  • Git: "Objeto suelto corrupto"
  • Git reset = fatal: no se puede leer el árbol
kenorb avatar Mar 27 '2014 17:03 kenorb

Estos son los pasos que seguí para recuperarme de un 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
  ...

El blob corrupto es 241091723c324aed77b2d35f97a05e856b319efd

2) Mueva el blob corrupto a un lugar seguro (por si acaso)

mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/

3) Obtener el padre de la mancha corrupta

git fsck --full
  Checking object directories: 100% (256/256), done.
  Checking objects: 100% (70321/70321), done.
  broken link from    tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
              to    blob 241091723c324aed77b2d35f97a05e856b319efd

El hash principal es 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180 .

4) Obtener el nombre del archivo correspondiente al blob corrupto

git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
  ...
  100644 blob 241091723c324aed77b2d35f97a05e856b319efd    dump.tar.gz
  ...

Busque este archivo en particular en una copia de seguridad o en el repositorio git ascendente (en mi caso es dump.tar.gz ). Luego cópielo en algún lugar dentro de su repositorio local.

5) Agregue un archivo previamente dañado en la base de datos de objetos git

git hash-object -w dump.tar.gz

6) ¡Celebra!

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)
Jonathan Maim avatar Oct 30 '2015 03:10 Jonathan Maim