Essayez d'abord les commandes suivantes (ré-exécutez-les si nécessaire) :
$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase
Et puis si vous avez encore des problèmes, essayez de le faire :
-
supprimer tous les objets corrompus, par exemple
fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
$ rm -v .git/objects/06/91c5...51e5
-
supprimer tous les objets vides, par exemple
error: object file .git/objects/06/91c5...51e5 is empty
$ find .git/objects/ -size 0 -exec rm -vf "{}" \;
-
vérifier un message "lien brisé" en :
git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
Cela vous indiquera de quel fichier provient le blob corrompu !
-
pour récupérer le fichier, vous pourriez avoir beaucoup de chance, et il pourrait s'agir de la version que vous avez déjà extraite dans votre arbre de travail :
git hash-object -w my-magic-file
encore une fois, et s'il sort le SHA1 manquant (4b945..) vous avez maintenant tout fait !
-
En supposant que c'est une ancienne version qui était cassée, la façon la plus simple de le faire est de faire :
git log --raw --all --full-history -- subdirectory/my-magic-file
et cela vous montrera l'ensemble du journal pour ce fichier (veuillez réaliser que l'arbre que vous avez n'est peut-être pas l'arbre de premier niveau, vous devez donc déterminer vous-même dans quel sous-répertoire il se trouvait), vous pouvez alors recréer l'objet manquant avec hash-object à nouveau.
-
pour obtenir une liste de tous les refs avec des commits, arbres ou blobs manquants :
$ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
Il se peut qu'il ne soit pas possible de supprimer certaines de ces références en utilisant les commandes normales branch -d ou tag -d, car elles mourront si git remarque la corruption. Utilisez donc la commande de plomberie git update-ref -d $ref à la place. Notez que dans le cas de branches locales, cette commande peut laisser une configuration de branche périmée dans .git/config. Elle peut être supprimée manuellement (cherchez la section [branch "$ref"]).
-
Après que tous les refs soient nettoyés, il peut encore y avoir des commits cassés dans le reflog. Vous pouvez effacer tous les reflogs en utilisant git reflog expire --expire=now --all. Si vous ne voulez pas perdre tous vos reflogs, vous pouvez rechercher les reflogs cassés dans les refs individuels :
$ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
(Notez l'option -g ajoutée à git rev-list.) Ensuite, utilisez git reflog expire --expire=now $ref sur chacune d'entre elles. Lorsque toutes les réfs et reflogs cassées ont disparu, lancez git fsck --full afin de vérifier que le dépôt est propre. Les objets en suspens sont Ok.
Vous trouverez ci-dessous l'utilisation avancée de commandes qui peuvent potentiellement causer la perte de vos données dans votre dépôt git si elles ne sont pas utilisées à bon escient, alors faites une sauvegarde avant de causer accidentellement d'autres dommages à votre git. Essayez à vos risques et périls si vous savez ce que vous faites.
Tirer la branche courante sur le dessus de la branche amont après le fetching :
$ git pull --rebase
Vous pouvez également essayer d'extraire la nouvelle branche et de supprimer l'ancienne :
$ git checkout -b new_master origin/master
Pour trouver l'objet corrompu dans git afin de le supprimer, essayez la commande suivante :
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
Pour OSX, utilisez sed -E
au lieu de sed -r
.
L'autre idée est de décompresser tous les objets des fichiers pack pour régénérer tous les objets dans .git/objects, donc essayez d'exécuter les commandes suivantes dans votre dépôt :
$ 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 ce qui précède ne vous aide pas, vous pouvez essayer de rsync ou de copier les objets git d'un autre dépôt, par exemple.
$ 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
Pour corriger la branche cassée lors de la tentative de checkout comme suit :
$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625
Essayez de le supprimer et de vérifier à nouveau en amont :
$ git branch -D master
$ git checkout -b master github/master
Au cas où git vous mettrait dans un état de détachement, vérifiez le fichier master
et y fusionner la branche détachée.
Une autre idée est de rebaser le master existant de manière récursive :
$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master
Voir aussi :
2 votes
Ça vient de m'arriver. Je ne veux pas m'embrouiller avec les objets git... j'ai donc cloné à nouveau le projet à partir du dépôt distant dans un nouveau dossier, puis j'ai simplement copié tous les fichiers de mes dépôts problématiques (à l'exception du fichier
.git
bien sûr) dans le repo fraîchement cloné... et a ensuite faitgit status
dans le nouveau repo... git détecte correctement toutes les modifications affectées à mes fichiers et je peux recommencer mon travail.