¿Cómo recuperar objects Git dañados por fallas en el disco duro?

Tuve una falla en el disco duro que ocasionó daños en algunos files de un repository de Git. Cuando git fsck --full obtengo 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 stonetworking block lengths) error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted 

Tengo copys de security del repository, pero la única copy de security que incluye el file del package ya está dañado. Así que creo que tengo que encontrar una manera de recuperar los objects individuales de diferentes copys de security y de alguna manera orderar a Git que produzca un nuevo package con solo objects correctos.

¿Puedes darme pistas sobre cómo arreglar mi repository?

En algunas copys de security anteriores, es posible que los objects incorrectos se hayan empaquetado en files diferentes o que aún sean objects sueltos. Entonces tus objects pueden ser recuperados.

Parece que hay algunos objects malos en su database. Entonces podrías hacerlo de forma manual.

Debido a git hash-object , git mktree y git commit-tree no escriben los objects porque se encuentran en el package, y luego comienzan a hacer esto:

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

(Sus packages se sacan del repository y se vuelven a desempacar, solo los objects buenos están ahora en la database)

Tu puedes hacer:

 git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee 

y verifica el tipo del object.

Si el tipo es blob: recupera el contenido del file de copys de security previas (con git show o git cat-file o git unpack-file ; entonces puedes git hash-object -w para reescribir el object en tu repository actual).

Si el tipo es tree: puede usar git ls-tree para recuperar el tree de copys de security anteriores; luego git mktree para escribirlo nuevamente en su repository actual.

Si el tipo es commit: lo mismo con git show , git cat-file y git commit-tree .

Por supuesto, haría una copy de security de su copy de trabajo original antes de comenzar este process.

Además, eche un vistazo a Cómo recuperar el object blob corrupto .

Banengusk me estaba poniendo en el path correcto. Para mayor reference, quiero publicar los pasos que tomé para corregir mi corrupción del repository. Tuve la suerte de encontrar todos los objects necesarios en packages anteriores o en copys de security de repositorys.

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

Pruebe los siguientes commands al principio (vuelva a ejecutar de nuevo si es necesario):

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

Y entonces usted todavía tiene los problemas, intente puede:

  • eliminar todos los objects corruptos, por ejemplo

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

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

     git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8 

    ¡Esto te dirá de qué file vino la gota corrupta!

  • para recuperar el file, puede ser realmente afortunado, y puede ser la versión que ya ha desprotegido en su tree de trabajo:

     git hash-object -w my-magic-file 

    de nuevo, y si emite el SHA1 (4b945 ..) que falta, ¡ya está todo listo!

  • suponiendo que era una versión anterior que se rompió, la forma más fácil de hacerlo es hacer:

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

    y eso le mostrará el logging completo de ese file (tenga en count que el tree que tenía puede no ser el tree de nivel superior, por lo que debe averiguar en qué subdirectory estaba), entonces puede volver a crear el file. Objeto perdido con hash-object nuevamente.

  • para get una list de todos los árbitros con compromisos faltantes, treees 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 algunos de esos refs con los commands normales de ramificación -d o de label -d, ya que morirán si git nota la corrupción. Entonces use el command de plomería git update-ref -d $ ref en su lugar. Tenga en count que en el caso de las sucursales locales, este command puede dejar atrás la configuration de la twig obsoleta en .git / config. Se puede eliminar manualmente (busque la sección [branch "$ ref"]).

  • Después de que todas las references estén limpias, es posible que aún haya commits rotos en el reflog. Puede borrar todos los reflogs usando git reflog expire –expire = now –all. Si no quiere perder todos sus reflogs, puede search los Refs individuales para reflogs 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 count la opción -g añadida a git rev-list). Luego, use git reflog expire –expire = now $ ref en cada uno de ellos. Cuando todos los refs y reflogs rotos se hayan ido, ejecute git fsck –full para verificar que el repository esté limpio. Los objects colgantes están bien.


A continuación puede encontrar un uso avanzado de los commands que potencialmente pueden causar la pérdida de sus datos en su repository de git si no se utilizan con prudencia, por lo que realice una copy de security antes de que accidentalmente haga más daños a su git. Pruebe su propio riesgo si sabe lo que está haciendo.


Para tirar de la twig actual en la parte superior de la twig ascendente después de ir a search:

 $ git pull --rebase 

También puede intentar extraer una nueva sucursal y eliminar la anterior:

 $ git checkout -b new_master origin/master 

Para encontrar el object dañado en git para su eliminación, intente con el siguiente command:

 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, use sed -E lugar de sed -r .


Otra idea es descomprimir todos los objects de los files del package para regenerar todos los objects dentro de .git / objects, así que intente ejecutar los siguientes commands dentro de su repository:

 $ 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 copyr los objects git de otro repository, por ej.

 $ 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 twig rota al intentar realizar el pago de la siguiente manera:

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

Intenta eliminarlo y pagar desde la parte superior de nuevo:

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

En caso de que si git te lleva a un estado separado, revisa el master y confúngalo en la twig separada.


Otra idea es volver a establecer la base del maestro existente recursivamente:

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

Ver también:

  • Algunos trucos para rebuild objects blob para arreglar un repository dañado.
  • ¿Cómo arreglar un repository roto?
  • ¿Cómo eliminar todas las references rotas de un repository?
  • ¿Cómo arreglar el repository git corrupto? (seeques)
  • ¿Cómo arreglar el repository git corrupto? (qnundrum)
  • Error al usar SourceTree con Git: 'Resumen' falló con el código 128: fatal: no se puede leer el tree
  • Recuperar un repository corrupto de Git Bare
  • Recuperando un repository git dañado
  • Cómo reparar el error de git: el object está vacío / corrupto
  • Cómo diagnosticar y corregir git fatal: no se puede leer el tree
  • Cómo lidiar con este error de git
  • ¿Cómo arreglar el repository git corrupto?
  • ¿Cómo 'sobrescribo', en lugar de 'fusionar', una twig en otra twig en Git?
  • ¿Cómo replace la twig principal en git, por completo, desde otra twig?
  • Git: "Objeto suelto corrupto"
  • Git reset = fatal: no se puede leer el tree

El process de pago de Git puede seleccionar files individuales de una revisión. Simplemente dele el hash de confirmación y el nombre del file. Información más detallada aquí.

Supongo que la manera más fácil de arreglar esto de forma segura es volver a la copy de security más reciente sin compromiso y luego seleccionar selectivamente los files no corruptos de las confirmaciones más recientes. ¡Buena suerte!

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

La mancha corrupta es 241091723c324aed77b2d35f97a05e856b319efd

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

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

3) Obtener padre 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 

El hash principal es 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180 .

4) Obtener el nombre del file correspondiente a blob corrupto

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

Encuentre este file en particular en una copy de security o en el repository upstream de git (en mi caso es dump.tar.gz ). Luego, cópielo en algún lugar dentro de su repository local.

5) Agregue el file previamente dañado en la database de objects 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) 

Aquí hay dos funciones que pueden ser útiles si la copy de security está dañada o también tiene algunas copys de security parcialmente dañadas (esto puede suceder si hace una copy de security de los objects dañados).

Ejecute ambos en el repository que está tratando de recuperar.

Advertencia estándar: solo úsela si está realmente desesperado y ha hecho una copy de security de su repository (corrupto). Esto podría no resolver nada, pero al less debería resaltar el nivel de corrupción.

 fsck_rm_corrupted() { corrupted='a' while [ "$corrupted" ]; do corrupted=$( \ git fsck --full --no-dangling 2>&1 >/dev/null \ | grep 'stonetworking 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 

y

 unpack_rm_corrupted() { corrupted='a' while [ "$corrupted" ]; do corrupted=$( \ git unpack-objects -r < "$1" 2>&1 >/dev/null \ | grep 'stonetworking 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 

He resuelto este problema para agregar algunos cambios como git add -A y git commit again.