Comment faire pour supprimer les blobs non référencés de mon git repo
j'ai un GitHub repo qui avait deux branches - master & release.
la branche de publication contenait des fichiers de distribution binaires qui contribuaient à une très grande taille de repo (> 250 Mo), donc j'ai décidé de nettoyer les choses.
  J'ai d'abord supprimé la branche de publication à distance, via  git push origin :release   
  puis j'ai supprimé la branche de publication locale. D'abord j'ai essayé  git branch -d release  , mais git a dit    "erreur: la branche 'release' est pas un ancêtre de votre TÊTE."   ce qui est vrai, alors j'ai fait  git branch -D release  pour le forcer à être supprimé.  
  mais la taille de mon dépôt, localement et sur GitHub, était encore énorme. Alors j'ai parcouru la liste habituelle des commandes git, comme  git gc --prune=today --aggressive  , sans succès.  
en suivant les instructions de Charles Bailey à SO 1029969 j'ai pu obtenir une liste de SHA1 pour les plus grands blobs. J'ai ensuite utilisé le script de DONC 460331 pour trouver les gouttes...et les cinq plus grands n'existent pas, bien que des petites taches soient trouvées, donc je sais que le script fonctionne.
je pense que ces blogs sont les binaires de la branche release, et ils ont d'une manière ou d'une autre été laissés après la suppression de cette branche. Quelle est la bonne façon de se débarrasser d'eux?
10 réponses
... et sans plus attendre, puis-je vous présenter ce script utile, git-gc-all , garanti pour supprimer all vos déchets git jusqu'à ce qu'ils pourraient venir des variables de configuration supplémentaires:
git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 \
    -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@"
vous pourriez aussi avoir besoin d'exécuter quelque chose comme ceux-ci d'abord, Oh mon Dieu, git est compliqué!!
git remote rm origin
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d
j'ai mis tout cela dans un script, ici:
http://sam.nipl.net/b/git-gc-all-ferocious
edit: vous pourriez aussi avoir besoin de supprimer quelques tags, merci Zitrax:
git tag | xargs git tag -d
comme décrit ici , il suffit d'utiliser
git reflog expire --expire-unreachable=now --all
git gc --prune=now
   git reflog expire --expire-unreachable=now --all  supprime toutes les références de commits inaccessibles dans  reflog .  
   git gc --prune=now  supprime les commits eux-mêmes.  
     Attention   : seule l'utilisation de  git gc --prune=now  ne fonctionnera pas car ces propagations sont encore référencées dans le refrog. Par conséquent, il est obligatoire d'effacer le nouveau carnet.  
 , Comme mentionné dans    cette SORTE de réponse    ,  git gc  peut en fait augmenter la taille de l'opération!  
Voir aussi ce fil 1519170920"
maintenant git a un mécanisme de sécurité pour pas supprimer les objets non référencés tout de suite lors de l'exécution "
git gc".
Par défaut, les objets non référencés sont conservés pour une période de 2 semaines. Ceci est pour vous faciliter la tâche de récupérer les branches supprimées accidentellement ou les propagations, ou pour éviter une course où un objet créé juste avant dans le processus d'être mais pas encore référencé pourrait être supprimé par un processus 'git gc' fonctionnant en parallèle.ainsi, pour donner ce délai de grâce aux objets emballés mais non référencés, le processus de reconditionnement pousse ces objets non référencés hors du pack dans leur forme lâche afin qu'ils puissent être vieillis et finalement élagués.
Les objets qui ne sont pas référencés sont généralement peu nombreux. Avoir 404855 objets non référencés c'est beaucoup, et être envoyé ces objets en premier lieu via un clone est stupide et un gaspillage complet de bande passante réseau.en tout cas... Pour résoudre votre problème, vous avez simplement besoin d'exécuter '
git gc"avec l'argument--prune=nowpour désactiver ce délai de grâce et se débarrasser de ces objets non référencés tout de suite (sûr seulement si aucun autre git les activités se déroulent en même temps, ce qui devrait être facile à assurer sur un poste de travail).et BTW, en utilisant
git gc --aggressive"avec une version git ultérieure (ougit repack -a -f -d --window=250 --depth=250')
le même fil mentionne :
 git config pack.deltaCacheSize 1
qui limite la taille du cache delta à un octet (le désactivant effectivement) au lieu de la valeur par défaut de 0 qui signifie illimité. Avec qui Je suis capable de reconditionner ce dépôt en utilisant la commande
git repackci-dessus sur un système x86-64 avec 4 Go de RAM et en utilisant 4 threads (c'est un Noyau quad). L'utilisation de la mémoire résidente augmente cependant à près de 3,3 GO.si votre machine est SMP et que vous n'avez pas assez de RAM, vous pouvez réduire le nombre de threads à un seul:
git config pack.threads 1
en outre, vous pouvez limiter l'utilisation de la mémoire avec le
--window-memory argumentàgit repack".
Par exemple, l'utilisation de--window-memory=128Mdevrait maintenir une limite supérieure raisonnable sur le delta l'utilisation de la mémoire de recherche bien que cela puisse avoir pour résultat une correspondance delta moins optimale si la contient beaucoup de fichiers volumineux.
sur le devant de la branche filtrante, vous pouvez considérer (avec prudence) ce script
#!/bin/bash
set -o errexit
# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2
if [ $# -eq 0 ]; then
    exit 0
fi
# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi
# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD
# remove the temporary history git-filter-branch otherwise leaves behind for a long time
rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --prune
   git gc --prune=now  , ou le faible niveau  git prune --expire now  .  
  chaque fois que votre tête bouge, git trace ceci dans le reflog . Si vous avez supprimé les "commits", vous avez toujours" dangling commits "parce qu'ils sont toujours référencés par le reflog  pendant ~30 jours. C'est le filet de sécurité lorsque vous supprimez s'engage par accident.  
 vous pouvez utiliser la commande git reflog  supprimer les propagations spécifiques, repack, etc.., ou juste la commande de haut niveau:  
git gc --prune=now
 vous pouvez utiliser git forget-blob .  
 l'usage est assez simple git forget-blob file-to-forget . Vous pouvez obtenir plus d'information ici  
il disparaîtra de tous les commits dans votre histoire, reconfigurer, tags et ainsi de suite
je rencontre le même problème de temps en temps, et à chaque fois je dois revenez à ce poste et d'autres, c'est pourquoi j'ai automatisé le processus.
crédits à des contributeurs tels que Sam Watkins
essayer d'utiliser git-filter - branch - ce n'est pas supprimer de gros blobs, mais peut supprimer de gros fichiers que vous spécifiez à partir de la pension entière. Pour moi, il réduit la taille de la pension de centaines de Mo à 12 Mo.
 avant de faire git filter-branch et git gc , vous devriez examiner les étiquettes qui sont présentes dans votre repo. Tout système réel qui dispose de tagging automatique pour des choses comme l'intégration continue et les déploiements fera des objets indésirables encore référencés par ces tags, donc  gc  ne peut pas les enlever et vous continuerez toujours à vous demander pourquoi la taille de repo est encore si grande.  
  la meilleure façon de se débarrasser de tous les trucs non désirés est de lancer  git-filter  &  git gc   et puis pousser maître à une nouvelle mise à nu. Le nouveau repo nu aura l'arbre nettoyé.  
parfois, la raison pour laquelle "gc" ne fait pas beaucoup de bien est qu'il y a un rebase inachevé ou un stash basé sur un vieux commit.
pour ajouter une autre astuce, n'oubliez pas d'utiliser git remote prune pour supprimer les branches obsolètes de vos télécommandes avant d'utiliser git gc
vous pouvez les voir avec branche git-a
c'est souvent utile quand on va chercher dans des dépôts GitHub ou fourchés...