web-dev-qa-db-fra.com

Comment restaurer un objet corrompu dans un référentiel git (pour les débutants)?

J'ai essayé d'ouvrir mon référentiel aujourd'hui et il n'y a eu aucun historique de validation. Tout ce que j'ai essayé (git status, git log, git checkout ...) a généré une erreur concernant un objet corrompu.

J'ai recherché ce problème en ligne et trouvé le article par Linus Torvalds, mais je me suis perdu au point où il a trouvé l'ID de lien brisé: aucun de mes ID de fichier, arbre ou blob, ne correspond à l'ID de coupable lancé par le message d'erreur.

Je suis ensuite retourné à l'article sur la récupération "objets git endommagés par une défaillance du disque dur" et (après avoir éloigné l'objet coupable) j'ai continué jusqu'à ce que

$ cat packed-refs

à ce moment mon ordinateur a dit: cat: packed-refs: No such file or directory J'ai sauté cette étape et j'ai fait

$ git fsck --full

et obtenu la sortie appropriée, mais ensuite j'étais censé copier le coupable (ou ce que j'appelais le coupable, l'ID sha1 jeté par l'erreur) d'un référentiel de sauvegarde dans le référentiel principal, puis copier les objets manquants de le référentiel de sauvegarde dans le référentiel principal, pour autant que je sache; et je ne veux rien faire trop drastique ou je pourrais forcer quelque chose que je ne peux pas forcer plus tard.

Donc ma (mes) question (s) est (sont), est-ce que je devais avoir fait une sauvegarde ( ooh, alerte débutant ), ou est-ce que c'est arrivé quand J'ai déballé le fichier .pack? Et le "coupable" que je recopie est-il en fait un fichier propre, c'est-à-dire non corrompu?

(Je pense qu'il est juste de vous dire que j'ai été initialement confondu par un simple tiret dans le fichier de Torvalds entre le "git" et le "fsck". Donc je suis [~ # ~] vraiment [~ # ~] nouveau dans ce domaine.)

BUG-LIST

Bug d'origine:

$ git status
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

Bug après avoir déplacé un objet corrompu:

$ git status
fatal: bad object HEAD
$ git fsck --full
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

$ git ls-tree 2c1033501b82e301d47dbf53ba0a199003af25a8
040000 tree 4a8b0b3747450085b1cd920c22ec82c18d9311bd    folder1
040000 tree 33298295f646e8b378299191ce20b4594f5eb625    folder2
040000 tree dec82bad6283fc7fcc869c20fdea9f8588a2f1b2    folder3
040000 tree 4544967c6b04190f4c95b516ba8a86cab266a872    folder4

$ git ls-tree dec82bad6283fc7fcc869c20fdea9f8588a2f1b2
100644 blob 67bda6df733f6cd76fc0fc4c8a6132d8015591d8    fileA
100644 blob 4cb7272c9e268bfbd83a04e568d7edd87f78589c    fileB
100644 blob ce9e0f2cc4d3b656fa30340afbdfed47fe35f3ef    fileC

$ git ls-tree 4544967c6b04190f4c95b516ba8a86cab266a872
100644 blob d64fe3add8328d81b1f31c9dbd528956ab391fb6    fileD
100644 blob d1ebd7df7082abc5190d87caa821bf3edb7b68e8    fileE
100644 blob bb6cd264e47a3e5bc7beadf35ea13bac86024b02    ...
100644 blob 995d622b9012f4ef69921091d1e1a73f32aa94e6
100644 blob 9141dbd2b1c7931a6461195934b6599f5dfb485a 
100644 blob ab128da1d82907cd0568448dc089a7996d5f79d3
100644 blob 57b11a7eb408a79739d2bb60a0dc35c591340d18
100644 blob 118105291c1c6ca4a01744889ffafbb018bc7ed3
100644 blob 86b1dfda56d0603f16910228327751f869d16bdc
100644 blob 077fe0cddde0d0be9d0974f928f66815caca7b76
100644 blob c0b32fd0450f21994bdc53ea83d3cf0bccd74004
100644 blob 37b87a4d11453468c4ae04572db5d322cd2d1d80
100644 blob 79d39f8d4e57fa3a71664598a63b6dfd88149638
100644 blob ee07bbe3e8cb5d6bb79fb0cd52cfbc9bd830498d    files

$ git ls-tree 33298295f646e8b378299191ce20b4594f5eb625
100644 blob f9d6f45cd028aec97f761f00c5f4f2f6b50fb925    MoreFiles
100644 blob 0cb9eed1d0dd9214d54a03af1bda21f37b8c0d02
100644 blob 198e4f97ece735cce47b7e99b54f1b5fa99fabf5
100644 blob fc004212fa8e483e5a8ab35b508027c7a9a1cbfa
100644 blob 0c7d74c7a9a8337b4a9f20802b63d71d42287f89

$ git ls-tree 4a8b0b3747450085b1cd920c22ec82c18d9311bd
100644 blob 0320f5b23dd7cce677fac60b9ad03f418cff5c88    oneLASTfile

Après avoir reculé l'objet corrompu:

$ git log --raw --all
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

$ cat packed-refs
cat: packed-refs: No such file or directory

$ git fsck --full
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

Après avoir retiré le fichier:

$ git fsck --full`  
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

Après avoir déballé le fichier .pack:

$ git log
fatal: bad object HEAD

$ cat packed-refs
cat: packed-refs: No such file or directory

$ git fsck --full
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b
28
Humble Penguin

Bon alors. Nous pouvons voir dans le deuxième message d'erreur que l'objet corrompu que vous avez déplacé était un commit. (HEAD le pointait!) Malheureusement, cela signifie qu'il est difficile de le réparer manuellement. (Par "dur", je veux dire probablement impossible à moins que vous ne vous souveniez exactement du message de validation et de l'heure à laquelle vous avez effectué la validation.) Heureusement, cela signifie qu'il est facile de ressusciter une nouvelle validation avec le même contenu de fichier - vous aurez suffit de lui écrire un nouveau message.

Avant de commencer, consultez le contenu de .git/HEAD - si c'est un nom de branche, souvenez-vous-en pour plus tard.

Tout d'abord, nous devons déterminer quel aurait dû être le parent de ce commit. Vous pouvez utiliser git reflog pour regarder le reflog de HEAD, et trouver le SHA1 où HEAD était juste avant de faire le commit 016660b. Il devrait ressembler à ceci:

016660b HEAD@{n}: commit: <subject of commit>
1234abc HEAD@{n-1}: ...

Vous pouvez copier le SHA1 de la position précédente de HEAD et vérifier ce commit:

git checkout 1234abc

Ensuite, vous pouvez lire dans l'arborescence que votre commit corrompu avait:

git read-tree 2c1033501b82e301d47dbf53ba0a199003af25a8

Et puis engagez-vous!

git commit

Maintenant, il y a une question ici sur ce qui aurait dû arriver à vos succursales. Si HEAD pointait vers une branche (disons master) qui à son tour pointait vers le commit corrompu, nous voulons définitivement corriger cela:

git branch -d master       # remove the original master branch
git checkout -b master     # recreate it here

S'il y a d'autres branches qui contenaient le commit corrompu, vous devrez également faire une restauration sur elles - faites-moi savoir si vous avez besoin d'aide pour cela.

18
Cascabel

FWIW, voici une réponse qui est plus pratique que la plupart des réponses désespérément optimistes sur d'autres questions concernant les référentiels git corrompus - dont la plupart font l'hypothèse sans fondement que le mauvais OP peut `` simplement re-cloner à partir de la télécommande Origine!' Hmm. Mais. Attendez une seconde. Et si je suis l'origine?

L'horreur

L'histoire commence quand une tentative de lancer un simple git gc --aggressive A révélé que, à mon insu, mon repo - complètement local - git avait en quelque sorte été complètement arrosé: il n'a pas pu enregistrer quoi que ce soit au-delà de quelques mois, perdant ainsi la majorité de son histoire, et criait gutturalement chaque fois qu'on lui demandait de git fsck --full | grep -v dangling. Plusieurs objets ont été identifiés comme perdus par git fsck.

git-repair: Minimiser le travail manuel terrifiant depuis 2014

Après avoir paniqué et trouvé beaucoup de questions avec des réponses médiocres trop votées, il suffit de dire `` re-clone à partir de l'origine distante! '' - qui, permettez-moi de m'attarder sur ce point, je n'en ai pas parce que je suis l'origine - j'ai trouvé git-repair , a fait un simple Sudo aptitude install git-repair, et laissez-le faire tous les fastidieux correctifs automatisables qui m'auraient probablement pris des heures (veuillez: exécuter sur un copie de votre dépôt corrompu [duh], sans --force!)

Cela a permis de réduire la quantité d'horreur signalée par git fsck --full | grep -v dangling. Mais les choses au-delà de la mi-août étaient toujours inaccessibles.

En particulier, tout cela semblait s'articuler autour d'un commit qui ne pouvait pas être récupéré. Comment pourrais-je le récupérer? La recherche de débordement de pile n'a pas été d'une grande aide!

Vous avez une sauvegarde, non?

C'est là que j'ai eu la chance d'avoir une sauvegarde à partir de fin novembre. Vous prenez des sauvegardes, non? Dans mon cas, c'était un Zip manuel du dépôt (ma routine de sauvegarde quotidienne est une horrible chose incrémentielle tar que je n'ai jamais vraiment testée ... une toux) ... mais ouf, c'était assez bien. Il n'avait pas souffert de l'indignité qui avait affligé mon repo en direct.

Mais l'objet manquant ne semblait pas simplement être stocké dans le .git/objects/XY/RESTOFHASHBLAHBLAHBLAH De cette sauvegarde. C'est probablement parce que c'était un commit, pas un fichier. Je ne sais pas! git est de la magie pour moi, au-delà de ma capacité à comprendre. J'avais juste besoin d'une solution rapide. N'est-ce pas pourquoi nous sommes tous ici?

Récupérer des objets à partir d'une sauvegarde (que vous avez, non?)

Avec la sauvegarde maintenant en main, j'ai eu une idée hilarante et stupide, j'ai dit 'il n'y a aucun moyen que cela puisse fonctionner!', Et j'ai immédiatement trouvé que simplement exécuter naïvement cp -fr /path/to/repo_backup/.git/objects/* /path/to/repo_git-repaired/.git/objects Vers fusion de fichiers le répertoire .git/objects de la sauvegarde dans son homologue dans mon dépôt corrompu, quelque peu réparé ... a travaillé pour récupérer tout l'historique - de retour au bon vieux 'initial commit lol. Prouver le correctif: git fsck --full Était maintenant aussi satisfait (malgré tous les bits qui pendaient).

J'ai ensuite pris des sauvegardes des repos vivants/corrompus, partiellement réparés et apparemment récupérés sur un disque séparé, au cas où j'en aurais besoin à nouveau.

Vous devriez vérifier cette méthodologie et cette commande avant de l'exécuter, ou peut-être trouver une bien meilleure façon de penser que je suis trop paresseux. Je ne sais pas. Mais pour moi, cela a sauvé mon repo. Et au sujet de reconsidérer ce que je dis ...

Clauses de non-responsabilité infinies dans des combinaisons infinies

Maintenant, évidemment, tout cela comporte des mises en garde: vous devez tout essayer sur une copie de votre dépôt corrompu, lire toute la documentation, pensez à être un peu plus prudent que je ne l'étais (cette commande forcée cp), et ne me tenez pas responsable ou absolument responsable de tout ce qui ne va pas * ... mais cela vous donne quelque chose de mieux à essayer que 'simplement re-cloner à partir de la télécommande Origine! ', Non?

* Si, cependant, tout se passe à droite, un gros don pourrait être de mise. ;)

Si quelqu'un a besoin de moi, je lancerai un regard suspicieux dans la direction générale de mon lecteur de disque, en espérant trouver une routine de sauvegarde qui ne prendra pas des heures à deux chiffres pour la restauration (le cas échéant), et peut-être même en obtenir sommeil.

10
underscore_d

J'ai eu le même problème. Cependant, mon problème a été résolu avec la modification des autorisations des dossiers et sous-dossiers .git/objects (récursivement) sur le serveur. Quelque chose comme:

chmod -R 770 .git/objects

Je pense que ce n'est pas votre problème, mais dans mon cas, il a été résolu.

6
Ruhan