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.
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
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.
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
).
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
:
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
Comme ci-dessus mais utilisez --delete-folders
Java -jar bfg.jar --delete-folders YOUR_FOLDER_NAME some-big-repo.git
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
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.
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:
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
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/