web-dev-qa-db-fra.com

Comment supprimer des objets inutilisés d'un référentiel git?

J'ai accidentellement ajouté, validé et poussé un énorme fichier binaire avec ma toute dernière validation dans un référentiel Git.

Comment puis-je faire en sorte que Git supprime les objets qui ont été/ont été créés pour ce commit afin que mon .git le répertoire se réduit à nouveau à une taille saine?

Modifier : Merci pour vos réponses; J'ai essayé plusieurs solutions. Aucun n'a fonctionné. Par exemple, celui de GitHub a supprimé les fichiers de l'historique, mais le .git la taille du répertoire n'a pas diminué:

$ BADFILES=$(find test_data -type f -exec echo -n "'{}' " \;)

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $BADFILES" HEAD
Rewrite 14ed3f41474f0a2f624a440e5a106c2768edb67b (66/66)
rm 'test_data/images/001.jpg'
[...snip...]
rm 'test_data/images/281.jpg'
Ref 'refs/heads/master' was rewritten

$ git log -p # looks Nice

$ rm -rf .git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --Prune
Counting objects: 625, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (598/598), done.
Writing objects: 100% (625/625), done.
Total 625 (delta 351), reused 0 (delta 0)

$ du -hs .git
174M    .git
$ # still 175 MB :-(
76
Jonas H.

J'ai répondu à ça ailleurs, et je vais copier ici puisque j'en suis fier!

... et sans plus tarder, puis-je vous présenter ce script utile, git-gc-all, garanti pour supprimer tous vos déchets git jusqu'à ce qu'ils puissent proposer 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 "$@"

L'option --agressive peut être utile.

REMARQUE: cela supprimera TOUS les trucs non référencés, alors ne venez pas me pleurer si vous décidez plus tard que vous vouliez en garder certains!

Vous pourriez aussi avoir besoin d'exécuter quelque chose comme ça en premier, 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

Je mets tout cela dans un script, ici:

http://sam.nipl.net/b/git-gc-all-ferocious

115
Sam Watkins

Votre git reflog expire --all est incorrect. Il supprime les entrées de reflog qui sont plus anciennes que le délai d'expiration, qui par défaut est de 90 jours. Utilisation git reflog expire --all --expire=now.

Ma réponse à une question similaire traite du problème du nettoyage des objets inutilisés d'un référentiel.

25
Josh Lee

1) Supprimez le fichier du dépôt git (et non le système de fichiers):

  • git rm --cached path/to/file

2) Rétrécissez le référentiel en utilisant:

  • git gc,

  • ou git gc --aggressive

  • ou git Prune

ou une combinaison des éléments ci-dessus comme suggéré dans cette question: Réduire la taille du référentiel git

17
Jamie

Ce guide sur suppression des données sensibles peut s'appliquer, en utilisant la même méthode. Vous serez en train de réécrire l'historique pour supprimer ce fichier de chaque révision dans laquelle il était présent. Ceci est destructeur et provoquera des conflits de repo avec toute autre extraction, donc avertissez d'abord les collaborateurs.

Si vous souhaitez garder le binaire disponible dans le référentiel pour d'autres personnes, il n'y a pas vraiment de moyen de faire ce que vous voulez. C'est à peu près tout ou rien.

10
Daenyth

La clé pour moi s'est avérée être en cours d'exécution git repack -A -d -f et alors git gc pour réduire la taille du pack git unique que j'avais.

7
Andrew Charneski

Hy!

Git ne reçoit que les objets dont il a réellement besoin lors du clonage de référentiels (si je comprends bien)

Vous pouvez donc modifier le dernier commit en supprimant le fichier ajouté par erreur, puis pousser vos modifications dans le référentiel distant (avec l'option -f pour écraser également l'ancien commit sur le serveur)

Ensuite, lorsque vous créez un nouveau clone de ce dépôt, son répertoire .git doit être aussi petit qu'avant le ou les gros fichiers validés.

Facultativement, si vous souhaitez également supprimer les fichiers inutiles du serveur, vous pouvez supprimer le référentiel sur le serveur et envoyer votre copie nouvellement clonée (qui a l'historique complet)

6
u-foka

Voir "Suppression d'objets" dans le livre Pro Git:

http://git-scm.com/book/en/Git-Internals-Maintenance-and-Data-Recovery#Removing-Objects

Mise à jour: voir aussi BFG repo cleaner: http://rtyley.github.io/bfg-repo-cleaner/

4
Czarek Tomczak
git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --Prune-empty -- --all

N'oubliez pas de modifier Filename pour celui que vous souhaitez supprimer du référentiel.

4
Martin