Supprimer le fichier du dépôt git (historique)
(résolu, voir bas du corps de la question)
En cherchant cela depuis longtemps maintenant, ce que j'ai jusqu'à maintenant est:
- http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history / et
- http://progit.org/book/ch9-7.html
à peu près la même méthode, mais les deux laissent des objets en paquet fichier... Enliser.
Ce que j'ai essayé:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_name'
rm -Rf .git/refs/original
rm -Rf .git/logs/
git gc
ont encore des fichiers dans le pack, et c'est comme ça que je le sais:
git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3
et ceci:
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch file_name" HEAD
rm -rf .git/refs/original/ && git reflog expire --all && git gc --aggressive --prune
pareil...
essayé git clone
astuce, il a enlevé certains des fichiers (~3000 d'entre eux), mais les plus gros fichiers sont toujours là...
j'ai quelques gros fichiers hérités dans le dépôt, ~200M, et je ne veux vraiment pas là... Et je ne veux pas réinitialiser le dépôt à 0 : (
SOLUTION: C'est le chemin le plus court pour se débarrasser des fichiers:
- vérifier .git / packed-refs - mon problème était que j'avais là une ligne
refs/remotes/origin/master
pour un dépôt distant, supprimez-la, sinon git ne supprimera pas ces fichiers - (facultatif)
git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5
- pour vérifier les plus grands fichiers - (optionnel)
git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98
- pour vérifier ce que sont ces fichiers -
git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names'
- supprimer un fichier de toutes les révisions -
rm -rf .git/refs/original/
- pour supprimer la sauvegarde de git -
git reflog expire --all --expire='0 days'
- expirer tous les objets en vrac -
git fsck --full --unreachable
- pour vérifier s'il y a des objets en vrac -
git repack -A -d
- reconditionnement -
git prune
- pour finalement supprimer ces objets
8 réponses
Je ne peux pas en être sûr sans avoir accès à vos données de dépôt, mais je crois qu'il y a probablement un ou plusieurs réferences emballées faisant encore référence à de vieilles commits d'avant que vous n'ayez lancé git filter-branch
. Cela expliquerait pourquoi git fsck --full --unreachable
ne qualifie pas le gros blob d'objet inaccessible, même si vous avez expiré votre rechog et retiré les références originales (déballées).
voici ce que je ferais (après git filter-branch
et git gc
ont été faits):
1) Assurez-vous que les références originales ont disparu:
rm -rf .git/refs/original
2) expirent toutes les entrées de reflog:
git reflog expire --all --expire='0 days'
3) Vérifier s'il s'agit d'un vieux colis réf.
cela pourrait être délicat, en fonction du nombre de références emballées que vous avez. Je ne connais aucune commande Git qui automatise ça., donc je pense que vous devrez le faire manuellement. Faites une copie de sauvegarde de .git/packed-refs
. Maintenant, éditez .git/packed-refs
. Vérifier s'il s'agit d'anciens réf (en particulier, voir s'il a emballé l'un des réf de .git/refs/original
). Si vous en trouvez d'anciennes qui n'ont pas besoin d'être là, supprimez-les (supprimez la ligne correspondant à cette référence).
après avoir nettoyé le fichier packed-refs
, voir si git fsck
remarque les objets inaccessibles:
git fsck --full --unreachable
si cela a fonctionné, et git fsck
déclare maintenant votre grande tache comme inaccessible, vous pouvez passer à l'étape suivante.
4) Remballer votre archive compressé(s)
git repack -A -d
cela permettra de s'assurer que les objets inaccessibles sont déballés et stay unpacked.
5) Tailler en vrac (inaccessible) des objets
git prune
et ça devrait le faire. Git devrait vraiment avoir une meilleure façon de gérer les références emballées. Peut-être il ya une meilleure façon que je ne connais pas. En l'absence d'une meilleure solution, l'édition manuelle du fichier packed-refs
pourrait être la seule solution.
je recommande d'utiliser le BFG Repo-Cleaner , une alternative plus simple et plus rapide à git-filter-branch
spécifiquement conçu pour réécrire des fichiers à partir de l'histoire Git. Une façon dont il rend votre vie plus facile ici, c'est qu'il gère réellement tous références par défaut (toutes les étiquettes, les branches, les choses comme réfs/remotes/origin/master, etc) mais il est aussi 10-50x plus rapide.
Vous devez suivre attentivement ces étapes ici: http://rtyley.github.com/bfg-repo-cleaner/#usage - mais le bit de base est juste ceci: téléchargez le jar de BFG (nécessite Java 6 ou au-dessus) et exécutez cette commande:
$ java -jar bfg.jar --delete-files file_name my-repo.git
tout fichier nommé file_name
(qui n'est pas dans votre dernier commit) sera totalement supprimé de l'historique de votre dépôt. Vous pouvez ensuite utiliser git gc
pour nettoyer les morts de données:
$ git gc --prune=now --aggressive
le BFG est généralement beaucoup plus simple à utiliser que git-filter-branch
- les options sont adaptées autour de ces deux cas d'utilisation commune:
- Retrait Fou De Gros Fichiers
- suppression mots de passe, justificatifs d'identité & autres données privées
divulgation Complète: je suis l'auteur de la BFG Repo-Cleaner.
j'ai trouvé cela très utile en ce qui concerne la suppression d'un dossier entier car ce qui précède ne m'a pas vraiment aidé: https://help.github.com/articles/remove-sensitive-data .
j'ai utilisé:
git filter-branch -f --force \
--index-filter 'git rm -rf --cached --ignore-unmatch folder/sub-folder' \
--prune-empty --tag-name-filter cat -- --all
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now
j'essayais de me débarrasser d'un gros dossier dans l'histoire, et les réponses ci-dessus ont fonctionné, jusqu'à un certain point. Le fait est qu'ils ne fonctionnent pas si vous avez des étiquettes. Si le commit contenant le gros fichier est accessible à partir d'une balise, alors vous devrez ajuster la commande filter-branches thusly:
git filter-branch --tag-name-filter cat \
--index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \
--all --tags
voir: Comment puis-je supprimer les fichiers sensibles de l'histoire de git
ce qui précède échouera si le fichier n'existe pas dans un Rév. dans ce cas, le commutateur '--ignore-unmatch' le réparera:
git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch <filename>' HEAD
puis, pour obtenir tous les objets en vrac hors de la reprise de possession:
git gc --prune='0 days ago'
vous avez diverses raisons pour une taille encore grande git repo après git gc
, car il ne supprime pas tous les objets en vrac .
je détail les raisons dans " réduire le dépôt git de taille "
mais une astuce à tester dans votre cas serait de clone votre" nettoyé "Git repo et voir si le clone a la taille appropriée.
("nettoyé" repo "étant celui où vous avez appliqué le filter-branch
, puis gc
et prune
)
ceci devrait être couvert par la commande git obliterate
dans les Extras Git ( https://github.com/visionmedia/git-extras ).
git obliterate <filename>
j'ai eu le même problème et j'ai trouvé un grand tutoriel sur github qui expliquent étape par étape comment se débarrasser des fichiers que vous avez accidentellement commis.
Voici un petit résumé de la procédure Cupcake suggéré.
si vous avez un fichier nommé file_to_remove
à supprimer de l'historique:
cd path_to_parent_dir
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch file_to_remove' \
--prune-empty --tag-name-filter cat -- --all