web-dev-qa-db-fra.com

Supprimer le gros fichier .pack créé par git

J'ai archivé une charge de fichiers dans une branche, puis j'ai fusionné, puis j'ai dû les supprimer. Il me reste maintenant un gros fichier .pack dont je ne sais pas comment me débarrasser.

J'ai supprimé tous les fichiers en utilisant git rm -rf xxxxxx et j'ai aussi couru le --cached option aussi.

Quelqu'un peut-il me dire comment supprimer un fichier .pack volumineux qui se trouve actuellement dans le répertoire suivant:

.git/objects/pack/pack-xxxxxxxxxxxxxxxxx.pack

Dois-je simplement supprimer la branche que j’ai toujours mais que je n’utilise plus? Ou y a-t-il autre chose que j'ai besoin de courir?

Je ne suis pas sûr de la différence, mais il y a un cadenas contre le fichier.

Merci


MODIFIER

Voici quelques extraits de mon bash_history qui devraient donner une idée de la façon dont j'ai réussi à entrer dans cet état (supposons à ce stade que je travaille sur une branche git appelée 'my-branch' et que j'ai un dossier contenant plus de dossiers/des dossiers):

git add .
git commit -m "Adding my branch changes to master"
git checkout master
git merge my-branch
git rm -rf unwanted_folder/
rm -rf unwanted_folder/     (not sure why I ran this as well but I did)

Je pensais avoir aussi couru ce qui suit, mais cela n'apparaît pas dans l'histoire de bash avec les autres:

git rm -rf --cached unwanted_folder/

Je pensais aussi que je courais des commandes git (comme git gc) pour essayer de ranger le fichier de pack mais ils n'apparaissent pas non plus dans le fichier .bash_history.

82
user1116573

Le problème est que, même si vous avez supprimé les fichiers, ils sont toujours présents dans les révisions précédentes. C'est tout l'intérêt de Git, c'est que même si vous supprimez quelque chose, vous pouvez toujours le récupérer en accédant à l'historique.

Ce que vous cherchez à faire s'appelle la réécriture de l’historique et implique le git filter-branch commande.

GitHub a une bonne explication du problème sur son site. https://help.github.com/articles/remove-sensitive-data

Pour répondre plus directement à votre question, vous devez exécuter cette commande avec unwanted_filename_or_folder remplacé en conséquence:

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch unwanted_filename_or_folder' --Prune-empty

Cela supprimera toutes les références aux fichiers de l'historique actif du référentiel.

Prochaine étape: effectuer un cycle de CPG pour forcer toutes les références au fichier à expirer et à être purgées du fichier pack. Rien ne doit être remplacé dans ces commandes.

git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --Prune=now
166
loganfsmyth

Scénario A: Si vos gros fichiers n'ont été ajoutés qu'à une branche, vous n'avez pas besoin d'exécuter git filter-branch. Il vous suffit de supprimer la branche et d'exécuter le ramassage des ordures:

git branch -D mybranch
git reflog expire --expire-unreachable=all --all
git gc --Prune=all

Scénario B: Cependant, il semble que, d'après votre historique de bash, vous avez fusionné les modifications dans le maître. Si vous n'avez pas partagé les modifications avec qui que ce soit (pas de git Push encore). Le plus simple serait de réinitialiser le maître à avant la fusion avec la branche contenant les gros fichiers. Cela éliminera tous les commits de votre branche et tous les commits à maîtriser après la fusion. Ainsi, vous risquez de perdre les modifications - en plus des gros fichiers - que vous souhaitiez réellement:

git checkout master
git log # Find the commit hash just before the merge
git reset --hard <commit hash>

Puis exécutez les étapes du scénario A.

Scénario C: S'il y avait d'autres modifications de la branche o modifications sur le maître après la fusion que vous souhaitez conserver, il serait préférable de rebaser le maître et d'inclure de manière sélective les commits qui tu veux:

git checkout master
git log # Find the commit hash just before the merge
git rebase -i <commit hash>

Dans votre éditeur, supprimez les lignes correspondant aux commits ayant ajouté les gros fichiers, tout en laissant le reste tel quel. Sauvegarder et quitter. Votre branche principale ne doit contenir que ce que vous voulez et pas de gros fichiers. Notez que git rebase sans pour autant -p éliminera les commits de fusion, vous aurez donc un historique linéaire pour le maître après <commit hash>. Ceci est probablement acceptable pour vous, mais sinon, vous pouvez essayer avec -p, mais git help rebase dit combining -p with the -i option explicitly is generally not a good idea unless you know what you are doing.

Puis exécutez les commandes du scénario A.

6
onlynone

Une option:

courir git gc manuellement pour condenser un certain nombre de fichiers de pack en un ou plusieurs fichiers de pack. Cette opération est persistante (c’est-à-dire que le fichier de gros pack conservera son comportement de compression). Il peut donc être avantageux de compresser un référentiel périodiquement avec git gc --aggressive

Une autre option consiste à enregistrer le code et le fichier .git quelque part, puis à supprimer le fichier .git et de recommencer à utiliser le code existant, en créant un nouveau référentiel git (git init).

5
Michael Durrant

Comme déjà indiqué par loganfsmyth dans son réponse , vous devez purger l'historique git car les fichiers continuent d'exister même après leur suppression du référentiel. Docs officiels GitHub recommande BFG que je trouve plus facile à utiliser que filter-branch:

Suppression de fichiers de l'historique

Télécharger BFG à partir de leur site web. Assurez-vous d’avoir installé Java, puis créez un historique de clonage et de purge en miroir. Assurez-vous de remplacer YOUR_FILE_NAME avec le nom du fichier que vous souhaitez supprimer:

git clone --mirror git://example.com/some-big-repo.git
Java -jar bfg.jar --delete-files YOUR_FILE_NAME some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all && git gc --Prune=now --aggressive
git Push

Supprimer un dossier

Comme ci-dessus mais utilisez --delete-folders

Java -jar bfg.jar --delete-folders YOUR_FOLDER_NAME some-big-repo.git

Autres options

BFG permet également des options encore plus sophistiquées (voir docs ) comme celles-ci:

Supprimez tous les fichiers de plus de 100M de l'historique:

Java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git

Important!

Lorsque vous exécutez BFG, veillez à ce que YOUR_FILE_NAME et YOUR_FOLDER_NAME ne sont en effet que des noms de fichiers/dossiers. Ce ne sont pas des chemins, donc quelque chose comme foo/bar.jpg ne fonctionnera pas! À la place, tous les fichiers/dossiers portant le nom spécifié seront supprimés de l'historique des dépôts, quel que soit le chemin ou la branche où ils existaient.

5
Timo

Exécutez la commande suivante en remplaçant PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA avec le chemin du fichier que vous voulez supprimer, pas seulement son nom de fichier. Ces arguments vont:

  1. Forcer Git à traiter, sans extraire, l'historique complet de chaque branche et tag
  2. Supprime le fichier spécifié, ainsi que tous les commits vides générés à la suite
  3. Ecraser vos tags existants
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --Prune-empty --tag-name-filter cat -- --all

Cela supprimera de force toutes les références aux fichiers de l'historique actif du référentiel.

Prochaine étape: effectuer un cycle de GC pour forcer toutes les références au fichier à expirer et à être purgées du fichier de pack. Rien ne doit être remplacé dans ces commandes.

git update-ref -d refs/original/refs/remotes/Origin/master
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --Prune=now
1
Benjamin Wasula

Je suis un peu en retard pour le spectacle, mais au cas où la réponse ci-dessus ne résoudrait pas la question, je trouverais un autre moyen. Supprimez simplement le fichier volumineux spécifique de .pack. J'ai eu ce problème où j'ai archivé accidentellement un gros fichier de 2 Go. J'ai suivi les étapes expliquées dans ce lien: http://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/

1
Rishabh Kumar