web-dev-qa-db-fra.com

Supprimer le fichier du référentiel git (historique)

(résolu, voir le bas du corps de la question)
Vous cherchez cela depuis longtemps maintenant, ce que j'ai jusqu'à présent est:

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

Il y a toujours des fichiers dans le pack, et voici comment je le sais:

git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3

Et ça:

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...

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

J'ai de gros fichiers hérités dans le référentiel, ~ 200M, et je ne veux vraiment pas qu'ils y soient ... 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érifiez .git/pack-refs - mon problème était que j'avais là un refs/remotes/Origin/master ligne pour un dépôt distant, supprimez-le, 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 rechercher 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' - pour expirer tous les objets en vrac
  7. git fsck --full --unreachable - pour vérifier s'il y a des objets en vrac
  8. git repack -A -d - reconditionnement
  9. git Prune - pour enfin supprimer ces objets
76
Boris Churzin

Je ne peux pas dire avec certitude sans accès à vos données de référentiel, mais je pense qu'il y a probablement une ou plusieurs références compressées faisant toujours référence à d'anciennes validations avant d'exécuter 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 références d'origine (décompressées).

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

1) Assurez-vous que les références d'origine ont disparu:

rm -rf .git/refs/original

2) Expire toutes les entrées de reflog:

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

) Vérifiez les anciennes références emballées

Cela pourrait être délicat, selon le nombre de références emballées dont vous disposez. Je ne connais aucune commande Git qui automatise cela, donc je pense que vous devrez le faire manuellement. Faites une sauvegarde de .git/packed-refs. Maintenant éditez .git/packed-refs. Vérifiez les anciennes références (en particulier, voyez si elles contiennent toutes les références de .git/refs/original). Si vous en trouvez d'anciens qui n'ont pas besoin d'être là, supprimez-les (supprimez la ligne de cette référence).

Après avoir nettoyé le packed-refs fichier, voir si git fsck remarque 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) Remballez vos archives emballées

git repack -A -d

Cela garantira que les objets inaccessibles seront décompressés et rester décompressés.

5) Taillez les objets lâches (inaccessibles)

git Prune

Et cela devrait le faire. Git devrait vraiment avoir une meilleure façon de gérer les refs emballés. Il y a peut-être une meilleure façon que je ne connais pas. En l'absence d'une meilleure méthode, l'édition manuelle du packed-refs le fichier est peut-être la seule solution.

64
Dan Moulding

Je recommanderais d'utiliser BFG Repo-Cleaner , une alternative plus simple et plus rapide à git-filter-branch spécialement conçu pour réécrire des fichiers de l'historique Git. Une façon de vous faciliter la vie ici est qu'il gère en fait tous références par défaut (toutes les balises, les branches, des trucs comme refs/remotes/Origin/master, etc.) mais c'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 pot de BFG (nécessite Java 6 ou supérieur) 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 référentiel. Vous pouvez ensuite 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 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 et autres Données privées

Divulgation complète: je suis l'auteur du BFG Repo-Cleaner.

15
Roberto Tyley

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
6
Mike Averto

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

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

Voir: Comment supprimer des fichiers sensibles de l'historique de git

Ce qui précède échouera si le fichier n'existe pas dans une rév. Dans ce cas, le commutateur '--ignore-unmatch' le corrigera:

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

Ensuite, pour retirer tous les objets en vrac de la reposition:

git gc --Prune='0 days ago'
2
Wayne Conrad

Vous avez plusieurs raisons pour une taille de référentiel git encore grande après git gc, car il ne supprime pas tous les objets libres .

Je détaille ces raisons dans " réduire la taille du dépôt git "

Mais une astuce à tester dans votre cas serait de cloner votre dépôt Git "nettoyé" et voir si le clone a le taille appropriée.

("repo" nettoyé "" étant celui où vous avez appliqué le filter-branch, puis gc et Prune)

1
VonC

Cela devrait être couvert par le git obliterate commande dans Git Extras ( https://github.com/visionmedia/git-extras ).

git obliterate <filename>
1
Spain Train

J'ai eu le même problème et j'ai trouvé un excellent tutoriel sur github qui explique étape par étape comment se débarrasser des fichiers que vous avez accidentellement commis.

Voici un petit résumé de la procédure comme l'a suggéré Cupcake.

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
0
Cyril Leroux