162 votes

Comment supprimer les blobs non référencés de mon dépôt Git

J'ai un dépôt GitHub, qui avait les deux branches - maître et de libération.

La branche de version contenu binaire des fichiers de distribution qui contribuent à une très grande pensions de taille (> 250 MO), j'ai donc décidé de faire le ménage.

J'ai d'abord supprimé le déclenchement à distance de la branche, via git push origin :release

Ensuite, j'ai supprimé la libération locale de la branche. J'ai d'abord essayé git branch -d release, mais git dit "erreur: La direction de "libération" n'est pas un ancêtre de votre TÊTE." ce qui est vrai, alors je n' git branch -D release pour le forcer à être supprimé.

Mais mon référentiel de taille, à la fois localement et sur GitHub, était encore énorme. Alors j'ai couru à travers la liste habituelle des commandes git, comme git gc --prune=today --aggressive, avec pas de chance.

Par la suite Charles Bailey instructions AFIN 1029969 j'ai été en mesure d'obtenir une liste de SHA1s pour les plus grosses gouttes. J'ai ensuite utilisé le script de SORTE 460331 pour trouver les gouttes...et les cinq plus importants n'existent pas, si les plus petites gouttes sont trouvé, donc je sais que le script fonctionne.

Je pense que ces blogs sont les binaires de la version de la branche, et ils en quelque sorte obtenu à gauche après la suppression de la succursale. Quelle est la bonne façon de se débarrasser d'eux?

270voto

Sam Watkins Points 1299

... et sans plus tarder, je vous présente ce utile de script, git-gc-tous, la garantie de supprimer tous vos git ordures jusqu'à ce qu'ils pourraient venir supplémentaire variables de configuration:

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 \
    -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@"

L' --agressif option peut être utile.

Vous pourriez aussi avoir besoin de lancer quelque chose comme ces premiers, oh, 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

35voto

VonC Points 414372

Comme mentionné dans cette SORTE de réponse, git gc peut en fait augmenter la taille de l'opération!

Ce aussi ce fil

Maintenant git a un mécanisme de sécurité pour ne pas supprimer les objets non référencés immédiatement lors de l'exécution de 'git gc'.
Par défaut, les objets non référencés sont conservés pour une période de 2 semaines. C'est de le rendre facile pour vous de récupérer accidentellement supprimé des branches ou commet, ou pour éviter une course où un objet créé dans le processus de l'être, mais pas encore référencé peuvent être supprimés par un"git gc' processus s'exécutant en parallèle.

Alors pour que la période de grâce de paniers mais non référencées objets, le processus de remballage pousse ceux non référencées objets du pack dans leur lâche forme de sorte qu'ils peuvent être vieillis et finalement taillé.
Les objets deviennent non référencés ne sont généralement pas que beaucoup de bien. Ayant 404855 les objets non référencés est beaucoup, et d'être envoyé à ces objets, en premier lieu, par l'intermédiaire d'un clone est stupide et un gaspillage de la bande passante du réseau.

De toute façon... Pour résoudre votre problème, il vous suffit d'exécuter la commande 'git gc"avec l' --prune=now argument pour désactiver cette période de grâce, et de se débarrasser de ces non référencées objets (sûr que si aucune autre git activités se déroulent en même temps ce qui devrait être facile à faire sur un poste de travail).

Et BTW, à l'aide de 'git gc --aggressive' avec un plus tard de version git (ou 'git repack -a -f -d --window=250 --depth=250')

Le même thread mentionne:

 git config pack.deltaCacheSize 1

Qui limite le delta de la taille de la mémoire cache d'un octet (désactiver) au lieu de la valeur par défaut de 0, ce qui signifie illimité. Avec qui je suis en mesure de reconditionner ce référentiel à l'aide de la git repack de commande sur un système x86-64 avec 4 go de RAM et à l'aide de 4 fils (c'est un quad core). Résident de l'utilisation de la mémoire augmente à près de 3,3 GO.

Si votre machine est SMP et vous n'avez pas suffisamment de RAM, alors vous pouvez réduire le nombre de threads à un seul:

git config pack.threads 1

En outre, vous pouvez également limiter l'utilisation de la mémoire avec l' --window-memory argument 'git repack'.
Par exemple, à l'aide de --window-memory=128M devrait garder raisonnable de la limite supérieure de la delta de recherche, l'utilisation de la mémoire même si cela peut résulter en une réduction optimale du delta du match si le repo contient beaucoup de fichiers volumineux.


Sur le filtre-direction de l'avant, 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 0are still
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

21voto

Jakub Narębski Points 87537

git gc --prune=now , ou niveau bas git prune --expire now .

14voto

vdboor Points 6259

Chaque fois que votre HEAD se déplace, git le suit dans les reflog . Si vous avez supprimé les commits, vous avez toujours des "commits en suspens" car ils sont toujours référencés par le reflog pendant ~ 30 jours. C'est le filet de sécurité lorsque vous supprimez les commits par accident.

Vous pouvez utiliser la commande git reflog supprimer les commits, le remballer, etc., ou simplement la commande de haut niveau:

 git gc --prune=now
 

1voto

W55tKQbuRu28Q4xv Points 1547

Essayez d'utiliser git-filter-branch - cela ne supprime pas les gros blobs, mais peut supprimer les gros fichiers que vous spécifiez dans le référentiel entier. Pour moi, cela réduit la taille des pensions de centaines de Mo à 12 Mo.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X