Supprimer le dossier et son contenu de l’historique de git / GitHub

Je travaillais sur un repository sur mon compte GitHub et c’est un problème sur lequel je suis tombé.

  • Projet Node.js avec un dossier avec quelques paquets npm installés
  • Les paquets étaient dans le dossier node_modules
  • Ajout de ce dossier au repository git et envoi du code à github (ne pensait pas à la partie npm à ce moment là)
  • Réalisé que vous n’avez pas vraiment besoin que ce dossier fasse partie du code
  • Supprimé ce dossier, l’a poussé

Dans ce cas, la taille totale du repository git était d’environ 6 Mo, le code réel (à l’exception de ce dossier) étant seulement d’environ 300 Ko .

Maintenant, ce que je recherche à la fin est un moyen de se débarrasser des détails de ce dossier depuis l’histoire de git, donc si quelqu’un le clone, il n’a pas besoin de télécharger 6 Mo d’historique où les seuls fichiers réels qu’ils recevront. à partir du dernier commit serait 300KB.

J’ai cherché des solutions possibles pour cela et j’ai essayé ces 2 méthodes

  • Supprimer le fichier du repository git (historique)
  • http://help.github.com/remove-sensitive-data/
  • https://gist.github.com/1588371

The Gist semblait fonctionner correctement. Après avoir exécuté le script, il a montré qu’il se débarrassait de ce dossier et que 50 commits différents avaient été modifiés. Mais cela ne m’a pas laissé pousser ce code. Quand j’ai essayé de le pousser, il a dit que Branch up to date mais a montré que 50 commits ont été modifiés sur un git status . Les 2 autres méthodes n’ont pas aidé non plus.

Maintenant, même si cela montrait que l’historique de ce dossier était supprimé, quand j’ai vérifié la taille de ce repository sur mon hôte local, il était toujours autour de 6 Mo. (J’ai également supprimé le dossier refs/original mais je n’ai pas vu la modification de la taille du repository).

Ce que je cherche à clarifier, c’est qu’il existe un moyen de se débarrasser non seulement de l’historique des validations (qui est la seule chose qui m’est arrivée), mais aussi que ces fichiers restnt supposés être annulés.

Disons qu’une solution est présentée pour cela et est appliquée sur mon hôte local, mais ne peut pas être reproduite dans ce repo GitHub, est-il possible de cloner ce repo, de revenir au premier commit et de le pousser (ou cela veut-il dire que git ont toujours une histoire de tous ces commits? – aka. 6MB).

Mon but ultime ici est de trouver le meilleur moyen de se débarrasser du contenu des dossiers de git afin qu’un utilisateur n’ait pas besoin de télécharger 6 Mo de contenu et qu’il ait toujours les autres commits qui n’ont jamais touché le dossier des modules (c’est assez beaucoup d’entre eux) dans l’histoire de git.

Comment puis-je faire ceci?

Si vous êtes ici pour copier-coller du code:

Ceci est un exemple qui supprime node_modules de l’historique

 git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d echo node_modules/ >> .gitignore git add .gitignore git commit -m 'Removing node_modules from git history' git gc git push origin master --force 

Je trouve que l’option --tree-filter utilisée dans d’autres réponses peut être très lente, en particulier sur les référentiels plus volumineux avec beaucoup de validations.

Voici la méthode que j’utilise pour supprimer complètement un répertoire de l’historique git en utilisant l’option --index-filter , qui s’exécute beaucoup plus rapidement:

 # Make a fresh clone of YOUR_REPO git clone YOUR_REPO cd YOUR_REPO # Create tracking twigs of all twigs for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done # Remove DIRECTORY_NAME from all commits, then remove the refs to the old commits # (repeat these two commands for as many directories that you want to remove) git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch DIRECTORY_NAME/' --prune-empty --tag-name-filter cat -- --all git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d # Ensure all old refs are fully removed rm -Rf .git/logs .git/refs/original # Perform a garbage collection to remove commits with no refs git gc --prune=all --aggressive # Force push all twigs to overwrite their history # (use with caution!) git push origin --all --force git push origin --tags --force 

Vous pouvez vérifier la taille du référentiel avant et après le gc avec:

 git count-objects -vH 

En plus de la réponse populaire ci-dessus, je voudrais append quelques notes pour les systèmes Windows . La commande

 git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
  • fonctionne parfaitement sans aucune modification! Par conséquent, vous ne devez pas utiliser Remove-Item , del ou autre chose au lieu de rm -rf .

  • Si vous devez spécifier un chemin vers un fichier ou un répertoire, utilisez des barres obliques comme ./path/to/node_modules

La méthode la meilleure et la plus précise que j’ai trouvée consistait à télécharger le fichier bfg.jar: https://rtyley.github.io/bfg-repo-cleaner/

Puis lancez les commandes:

 git clone --bare https://project/repository project-repository cd project-repository java -jar bfg.jar --delete-folders node_modules git reflog expire --expire=now --all && git gc --prune=now --aggressive git push --mirror https://project/new-repository 

Si vous souhaitez supprimer des fichiers, utilisez l’option delete-files à la place:

 java -jar bfg.jar --delete-files *.pyc 

Terminer la recette copier-coller, en ajoutant simplement les commandes dans les commentaires (pour la solution de copier-coller), après les avoir testés:

 git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD echo node_modules/ >> .gitignore git add .gitignore git commit -m 'Removing node_modules from git history' git gc git push origin master --force 

Après cela, vous pouvez supprimer la ligne “node_modules /” de .gitignore

J’ai supprimé les dossiers bin et obj des anciens projets C # en utilisant git sur windows. Attention à

 git filter-branch --tree-filter "rm -rf bin" --prune-empty HEAD 

Il détruit l’intégrité de l’installation de git en supprimant le dossier usr / bin dans le dossier d’installation de git.