Saltar al contenido

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

Solución:

En algunas copias de seguridad anteriores, es posible que los objetos defectuosos se hayan empaquetado en diferentes archivos o que todavía sean objetos sueltos. Para que sus objetos puedan recuperarse.

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

Porque git hash-object, git mktree y git commit-tree no escriba los objetos porque se encuentran en el paquete, luego comience a hacer esto:

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

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

Tu puedes hacer:

git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

y verifique el tipo de objeto.

Si el tipo es blob: recupere el contenido del archivo de copias de seguridad anteriores (con git show o git cat-file o git unpack-file; entonces puedes git hash-object -w para reescribir el objeto en su repositorio actual.

Si el tipo es árbol: podría usar git ls-tree para recuperar el árbol de copias de seguridad anteriores; luego git mktree para escribirlo nuevamente en su repositorio actual.

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

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

Además, eche un vistazo a Cómo recuperar un objeto blob dañado.

Banengusk me estaba poniendo en el camino correcto. Para mayor referencia, quiero publicar los pasos que tomé para corregir la corrupción de mi repositorio. Tuve la suerte de encontrar todos los objetos necesarios en paquetes más antiguos o en las 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!

Pruebe los siguientes comandos al principio (vuelva a ejecutarlo si es necesario):

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

Y luego todavía tienes los problemas, intenta:

  • eliminar todos los objetos corruptos, p. ej.

    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, p. ej.

    error: object file .git/objects/06/91c5...51e5 is empty
    $ find .git/objects/ -size 0 -exec rm -vf "{}" ;
    
  • verifique un mensaje de “vínculo roto” mediante:

    git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
    

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

  • para recuperar el archivo, es posible que tenga mucha suerte, y puede ser la versión que ya ha verificado en su árbol de trabajo:

    git hash-object -w my-magic-file
    

    de nuevo, y si genera el SHA1 faltante (4b945 ..) ¡ya está todo listo!

  • asumiendo que se trataba de una versión anterior que estaba rota, 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 registro completo para 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), entonces ahora puede volver a crear el objeto perdido con objeto hash de nuevo.

  • para obtener una lista de todas las referencias con confirmaciones, árboles o blobs faltantes:

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

    Es posible que no sea posible eliminar algunas de esas referencias utilizando los comandos branch -d o tag -d regulares, ya que morirán si git nota la corrupción. Así que use el comando de plomería git update-ref -d $ ref en su lugar. Tenga en cuenta que en el caso de las ramas locales, este comando puede dejar una configuración obsoleta de la rama en .git / config. Se puede eliminar manualmente (busque el [branch “$ref”] sección).

  • Después de que todas las referencias estén limpias, aún puede haber confirmaciones rotas en el reflog. Puede borrar todos los reflogs usando git reflog expire –expire = now –all. Si no desea perder todos sus reflogs, puede buscar reflogs individuales en los 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 cuenta la opción -g agregada a git rev-list.) Luego, use git reflog expire –expire = now $ ref en cada uno de ellos. Cuando todos los refs y reflogs rotos hayan desaparecido, 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 con prudencia, así que haga una copia de seguridad antes de dañar accidentalmente su git. Pruébelo bajo su propio riesgo si sabe lo que está haciendo.


Para tirar de la rama actual en la parte superior de la rama ascendente después de buscar:

$ git pull --rebase

También puede intentar pagar una nueva rama y eliminar la anterior:

$ git checkout -b new_master origin/master

Para encontrar el objeto dañado en git para su eliminación, pruebe 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 -E en 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 rsync 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 el flujo ascendente:

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

En caso de que git lo lleve a un estado separado, consulte el master y fusionar en él la rama separada.


Otra idea es rebasar el 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 de git dañado? (seeques)
  • ¿Cómo reparar el repositorio de git dañado? (qnundrum)
  • Error al usar SourceTree con Git: ‘Resumen’ falló con el código 128: fatal: no se puede leer el árbol
  • Recuperar un repositorio Git Bare corrupto
  • Recuperar un repositorio de git dañado
  • Cómo corregir el error de git: el objeto está vacío / corrupto
  • Cómo diagnosticar y corregir git fatal: no se puede leer el árbol
  • Cómo lidiar con este error de git
  • ¿Cómo reparar el repositorio de git dañado?
  • ¿Cómo ‘sobrescribo’, en lugar de ‘fusionar’, una rama en otra rama en Git?
  • ¿Cómo reemplazar la rama maestra en git, por completo, desde otra rama?
  • Git: “Objeto suelto dañado”
  • Git reset = fatal: no se puede leer el árbol
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *