76 votes

Supprimer un fichier du dépôt git (historique)

(résolu, voir le bas du corps de la question)
Cela fait longtemps que je cherche cela, ce que j'ai jusqu'à présent, c'est.. :

A peu près la même méthode, mais les deux laissent des objets dans les fichiers pack... Coincé.
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

J'ai toujours des fichiers dans le pack, et c'est ainsi 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

Le même...

Essayé git clone truc, il a supprimé certains fichiers (~3000 d'entre eux) mais les plus gros fichiers sont toujours là...

J'ai quelques gros fichiers dans le dépôt, ~200M, et je ne veux vraiment pas qu'ils s'y trouvent... Et je ne veux pas réinitialiser le référentiel à 0 :(

SOLUTION : C'est le moyen le plus court de se débarrasser des fichiers :

  1. vérifier .git/packed-refs - mon problème était que j'avais là un refs/remotes/origin/master pour un dépôt distant, supprimez-la, sinon git ne supprimera pas ces fichiers.
  2. (facultatif) git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 - pour vérifier les fichiers les plus volumineux
  3. (facultatif) git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98 - pour vérifier quels sont ces fichiers
  4. git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names' - pour supprimer un fichier de toutes les révisions
  5. rm -rf .git/refs/original/ - pour supprimer la sauvegarde de git
  6. git reflog expire --all --expire='0 days' - d'expulser tous les objets en vrac
  7. git fsck --full --unreachable - vérifier s'il n'y a pas d'objets détachés
  8. git repack -A -d - reconditionnement
  9. git prune - pour enfin supprimer ces objets

64voto

Dan Moulding Points 46866

Je ne peux pas le dire avec certitude sans avoir accès aux données de votre dépôt, mais je pense qu'il y a probablement un ou plusieurs refs emballés qui font encore référence à d'anciens commits datant d'avant que vous n'exécutiez git filter-branch . Cela expliquerait pourquoi git fsck --full --unreachable n'appelle pas le gros blob un objet inaccessible, même si vous avez expiré votre reflog et supprimé les refs originaux (non emballés).

Voici ce que je ferais (après git filter-branch y git gc ont été faites) :

1) S'assurer que les arbitres originaux ont disparu :

rm -rf .git/refs/original

2) Expirer toutes les entrées de reflog :

git reflog expire --all --expire='0 days'

3) Vérifier la présence de vieilles références emballées

Cela pourrait s'avérer délicat, en fonction du nombre d'arbitres emballés que vous avez. Je ne connais pas de commande Git qui automatise cela, donc je pense que vous devrez le faire manuellement. Faites une sauvegarde de .git/packed-refs . Modifier maintenant .git/packed-refs . Vérifier les anciennes références (en particulier, voir s'il a empaqueté les références de .git/refs/original ). Si vous trouvez d'anciennes références qui n'ont pas lieu d'être, supprimez-les (supprimez la ligne correspondant à cette référence).

Une fois que vous avez fini de nettoyer le packed-refs voir si le fichier git fsck signale les objets inaccessibles :

git fsck --full --unreachable

Si cela a fonctionné, et git fsck signale maintenant que votre gros blob est inaccessible, vous pouvez passer à l'étape suivante.

4) Repackez votre (vos) archive(s) emballée(s)

git repack -A -d

Cela permettra de s'assurer que les objets inaccessibles sont déballés et séjour déballé.

5) Élaguer les objets non fixés (inaccessibles)

git prune

Cela devrait suffire. Git devrait vraiment avoir un meilleur moyen de gérer les refs emballés. Peut-être existe-t-il un meilleur moyen que je ne connais pas. En l'absence d'une meilleure méthode, l'édition manuelle du fichier packed-refs pourrait être la seule solution.

15voto

Roberto Tyley Points 4352

Je recommande d'utiliser l'option BFG Repo-Cleaner une alternative plus simple et plus rapide à l'utilisation de git-filter-branch spécialement conçu pour réécrire les fichiers de l'historique Git. L'une des façons de vous faciliter la vie est qu'il prend en charge les fichiers tous par défaut (tous les tags, branches, trucs comme refs/remotes/origin/master, etc) mais c'est aussi 10-50x plus rapide.

Vous devez suivre attentivement les étapes décrites ici : http://rtyley.github.com/bfg-repo-cleaner/#usage - mais l'essentiel est là : téléchargez le fichier Le bocal de BFG (nécessite Java 6 ou plus) 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 le plus récent engager) sera sera sera totalement supprimée de l'historique de votre dépôt. Vous pouvez alors utiliser git gc pour nettoyer les données mortes :

$ git gc --prune=now --aggressive

Le BFG est généralement beaucoup plus simple à utiliser que le git-filter-branch - les options sont adaptées à ces deux cas d'utilisation courants :

  • Suppression Crazy Big Files
  • Suppression Mots de passe, informations d'identification & autres Données privées

Révélation complète : je suis l'auteur du BFG Repo-Cleaner.

6voto

Mike Averto Points 311

J'ai trouvé cela très utile pour supprimer 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

5voto

BHMulder Points 426

J'essayais de me débarrasser d'un gros fichier dans l'historique, et les réponses ci-dessus ont fonctionné, jusqu'à un certain point. Le problème est qu'elles ne fonctionnent pas si vous avez des balises. Si le commit contenant le gros fichier est accessible à partir d'une balise, alors vous devrez ajuster la commande filter-branches de la manière suivante :

git filter-branch --tag-name-filter cat \
--index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \
--all --tags

2voto

Wayne Conrad Points 31052

Voir : Comment supprimer les fichiers sensibles de l'historique de git ?

L'opération ci-dessus échouera si le fichier n'existe pas dans un répertoire. Dans ce cas, l'option '--ignore-unmatch' corrigera le problème :

git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch <filename>' HEAD

Ensuite, il s'agit de retirer tous les objets non fixés du dépôt :

git gc --prune='0 days ago'

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