07.01.08

Récupérer un repo Git accidenté ( fatal: Not a git repository )

Posted in Programmation at 0:10 par denis

Allez savoir pourquoi ca arrive toujours au plus mauvais moment… Allez d’ailleurs savoir pourquoi, mais Git a décidé ce soir de me faire une petite crasse… En plein boulot, voila-t-il pas que la sale bête se met à me traiter de « Pas un git repositoire », alors que j’essayais gentiment de faire mon commit du soir ( très important pour un bon sommeil, notez bien ).

Au premier coup d’oeil pourtant, tout va bien: le répetoire .git est bien là. Mais git-fsck n’est pas d’accord. Et il le fait savoir, comme son ami commit 30 secondes plus tôt:

fatal: Not a git repository

Voila qui est bien facheux… D’ailleurs un petit coup de strace sur la commande a tôt fait de révéler l’infamie responsable de tout ca: on a amputé mon gentil répo de ses fichiers .git/HEAD et carrément de tout le contenu de .git/refs ! Allez savoir quel terroriste est reponsable de ca, serait-ce l’infame XFS ? Un bug dans Git ?

Peu importe, le mal est fait, maintenant, faut récupérer. Alors voyons ce qu’il nous reste. Pas grand chose en fait: en gros, il reste surtout .git/log, .git/objects et .git/packed-refs. Premier « ouf » sonore: mes objets sont encore la, reste à récupérer les références, et pour ca, j’ai encore du bol: il me reste le log.

Primo, voyons le fichier .git/log/HEAD. Il contient en fait tout l’historique du pointeur HEAD pour cette copie de travail. La dernière ligne contient une référence au HEAD d’avant le crash. Dans mon cas, elle ressemble à ça:
edc483686bfcf0d889233eb03128424daa46f351 0cb4c60700197427926856a71a389bf6cba0221e Denis Wernert <deniswernert@nymphadora> 1214865337 +0200    checkout: moving from master to wip
Notez la seconde somme SHA1 de la ligne, 0cb4c60700197427926856a71a389bf6cba0221e, c’est elle, la référence qu’on cherche. On va la coller dans le fichier .git/HEAD, ce sera déjà ça.

C’est déjà pas mal, mais ca ne suffit pas, il faut encore re-créer .git/refs. Notez que .git/log contient un répertoire refs, contenant lui-même un répertoire heads. Pour chaque fichier contenu dans .git/log/refs/heads, on va créer un fichier dans .git/refs/heads du même nom, et pour chacun, on procedera comme pour le fichier HEAD ci dessus, c’est à dire qu’on va recopier la seconde somme SHA1 de la dernière ligne, pour la placer dans le fichier de destination.

Et la, ca va mieux.

Les branches sont de retour, et git-status veut bien me parler à nouveau. Notez que pour l’instant, ma référence à HEAD est absolue, et de fait, git ne reconnait pas ma branche courante. Une fois certain d’avoir tout retrouvé et après avoir sauvé mes modifs locales dans un patch, je peux écrire

ref: refs/heads/wip

dans mon HEAD, ou bien tout simplement faire un

git checkout wip

pour remettre le pointeur sur la branche.
Et voila, le répo est revenu et enfin dans de bonnes dispositions. Dans ce cas ci, on pourra bien dire que la « hackabilité » de Git m’a été bien utile…

Partagez cet article:
  • Technorati
  • Slashdot
  • digg
  • del.icio.us
  • YahooMyWeb
  • scuttle

Laisser un commentaire

You must be logged in to post a comment.