Comment faire pour que Git «oublie» un fichier qui a été suivi mais qui est maintenant dans .gitignore?

5407

Il y a un fichier qui était suivi git, mais maintenant le fichier est sur la .gitignoreliste.

Cependant, ce fichier continue de s'afficher git statusaprès sa modification. Comment forcez-vous gità l'oublier complètement?

Ivan
la source
16
git clean -Xsemble similaire, mais il ne s'applique pas dans cette situation (lorsque les fichiers sont toujours suivis par Git). J'écris ceci pour quiconque cherche une solution pour ne pas suivre la mauvaise route.
imz - Ivan Zakharyaschev
35
La seule vraie réponse à cela est ci-dessous, voir git update-index --assume-unchanged. Cette solution 1) conserve le fichier sur le serveur (index), 2) vous permet de le modifier librement localement.
Qwerty
8
Vous devez utiliser --skip-worktree, voir: stackoverflow.com/questions/13630849/…
Doppelganger
77
Une question importante est: le fichier doit-il rester dans le référentiel ou non? Par exemple, si une nouvelle personne clone le dépôt, devrait-elle obtenir le fichier ou non? Si OUI puis git update-index --assume-unchanged <file>est correcte et le fichier restera dans le référentiel et les changements ne seront pas ajoutés avec git add. Si NON (par exemple, il s'agissait d'un fichier cache, d'un fichier généré, etc.), git rm --cached <file>le supprimera du référentiel.
Martin
9
@Martin @Qwerty Everyon devrait s'arrêter pour vous conseiller sur les --assume-unchangedperformances afin d'empêcher git de vérifier l'état des gros fichiers suivis, mais préfère --skip-worktreelequel est pour les fichiers suivis modifiés que l'utilisateur ne veut plus engager. Voir stackoverflow.com/questions/13630849/…
Philippe

Réponses:

5709

.gitignoreempêchera les fichiers non suivis d'être ajoutés (sans an add -f) à l'ensemble des fichiers suivis par git, cependant git continuera à suivre tous les fichiers qui sont déjà suivis.

Pour arrêter le suivi d'un fichier, vous devez le supprimer de l'index. Cela peut être réalisé avec cette commande.

git rm --cached <file>

Si vous souhaitez supprimer un dossier entier, vous devez supprimer tous les fichiers qu'il contient récursivement.

git rm -r --cached <folder>

La suppression du fichier de la révision de tête aura lieu lors du prochain commit.

AVERTISSEMENT: bien que cela ne supprime pas le fichier physique de votre section locale, il supprimera les fichiers des autres machines des développeurs la prochaine fois git pull.

CB Bailey
la source
55
le processus qui fonctionnait pour moi était 1. valider d'abord les modifications en attente 2. git rm --cached <fichier> et valider à nouveau 3. ajouter le fichier à .gitignore, vérifier avec le statut git et valider à nouveau
mataal
117
Ajout très important. Si le fichier ignoré est modifié (mais malgré cela ne doit pas être validé), après modification et exécution, git add .il est ajouté à l'index. Et le prochain commit le validerait dans le référentiel. Pour éviter cela, exécutez juste après tout ce que mataal a dit une autre commande:git update-index --assume-unchanged <path&filename>
Dao
32
La méthode de @AkiraYamamoto a également bien fonctionné pour moi. Dans mon cas, j'ai supprimé la sortie car mon référentiel contenait des milliers de fichiers:git rm -r -q --cached .
Aaron Blenkush
85
Cela supprimera le fichier git pull.
Petr Peller
22
git rm --cached <fichier> supprime simplement le fichier du référentiel, git update-index --assume-unchanged <fichier> fichier non affiché dans les modifications non mises en scène et ne fait pas tirer de nouvelles modifications. Mais je veux GIT JUSTE IGNORER LE CONTENU DU FICHIER PLEEEEEASE
Igor Semin
2613

La série de commandes ci-dessous supprimera tous les éléments de l'index Git (pas du répertoire de travail ou du référentiel local), puis mettra à jour l'index Git, tout en respectant git ignore. PS. Index = Cache

Première:

git rm -r --cached . 
git add .

Alors:

git commit -am "Remove ignored files"

Ou à une ligne:

git rm -r --cached . && git add . && git commit -am "Remove ignored files"
Matt Frear
la source
197
Pour mettre en évidence la différence entre cette réponse et celle acceptée: En utilisant ces commandes, vous n'avez pas besoin de connaître réellement les fichiers affectés. (Imaginez un répertoire temporaire avec beaucoup de fichiers aléatoires qui devraient être effacés de l'index).
Ludwig
53
Identique à la réponse acceptée. Les fichiers seront supprimés le git pull.
Petr Peller
73
Ce serait bien d'avoir ceci comme une commande git standard. Quelque chose comme git rmignored.
Berik
12
@gudthing -r signifie "récursif"
Mark
14
Avec cela, vous pouvez finir par ajouter d' autres fichiers inutiles qui ne sont pas actuellement .gitignore. Ce qui peut être difficile à déterminer si cela dépend du niveau de bruit git statusaprès cette commande. Une commande qui ne supprime que les fichiers nouvellement ignorés serait préférable. C'est pourquoi je préfère la réponse de
thSoft
1123

git update-index fait le travail pour moi:

git update-index --assume-unchanged <file>

Remarque: Cette solution est en fait indépendante .gitignorecar gitignore ne concerne que les fichiers non suivis.

edit: Depuis que cette réponse a été publiée, une nouvelle option a été créée et cela devrait être préféré. Vous devez utiliser --skip-worktreece qui est pour les fichiers suivis modifiés que l'utilisateur ne veut plus engager et conserver --assume-unchangedpour les performances afin d'empêcher git de vérifier l'état des gros fichiers suivis. Voir https://stackoverflow.com/a/13631525/717372 pour plus de détails ...

git update-index --skip-worktree <file>
Konstantin
la source
173
C'EST la vraie réponse. Génial en fait, très simple, ne pollue pas git statuset en fait très intuitif. Merci.
Pablo Olmos de Aguilera C.12
4
J'ai rm [...] .opté pour la bonne solution, car au moins je pouvais comprendre comment cela fonctionnait. Je n'ai trouvé aucune excellente documentation sur quoi faire update-indexet quoi --assume-unchangedfaire. Quelqu'un peut-il ajouter comment cela se compare à l'autre, en ce que je voudrais supprimer tous les fichiers qui auraient été ignorés? (Ou un lien pour une explication claire?)
Brady Trainor
25
git update-index --assume-unchanged <path> …git ignorera les changements dans les chemins spécifiés, indépendamment de .gitignore. Si vous extrayez d'une télécommande et que celle-ci a des modifications sur ce chemin, git échouera la fusion avec un conflit et vous devrez fusionner manuellement. git rm --cached <path> …git arrêtera de suivre ce chemin. Si vous n'ajoutez pas le chemin, .gitignorevous verrez le chemin à l'avenir git status. La première option a moins de bruit dans l'historique de validation de git et permet de distribuer les modifications du fichier "ignoré" à l'avenir.
ManicDee
26
Je suis assez confus quant à la façon dont ce n'est pas la réponse acceptée. La réponse acceptée ici ne répond clairement pas à la vraie question posée. Cette réponse ignore les modifications apportées au fichier qui se trouve dans le référentiel sans le supprimer du référentiel.
Dave Cooper
11
Cette réponse serait beaucoup plus utile si elle expliquait exactement ce que fait la commande donnée, par exemple en quoi elle est différente des autres solutions suggérées.
LarsH
283
git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"

Cela prend la liste des fichiers ignorés et les supprime de l'index, puis valide les modifications.

thSoft
la source
7
Si vous devez également les supprimer du répertoire de travail, exécutez simplement git ls-files --ignored --exclude-standard | xargs git rm . Je crois que cette réponse est la meilleure! Parce que c'est très clair, Unix-way, et fait la chose souhaitée de manière directe, sans composer les effets secondaires d'autres commandes plus complexes.
imz - Ivan Zakharyaschev
6
Très bonne réponse; cependant, la commande échouera si vous avez des chemins avec des espaces au milieu, par exemple: "My dir / my_ignored_file.txt"
David Hernandez
8
git ls-files --ignored --exclude-standard | sed 's /.*/"&"/' | xargs git rm --cached
David Hernandez
3
git rmse plaindra si ls-filesne correspond à rien. Utilisez xargs -r git rm ...pour dire de xargsne pas s'exécuter git rmsi aucun fichier ne correspond.
Wolfgang
10
Il serait préférable d'utiliser \ 0 comme séparateur:git ls-files --ignored --exclude-standard -z|xargs -0 git rm --cached
Nils-o-mat
83

J'utilise toujours cette commande pour supprimer ces fichiers non suivis. Une ligne, style Unix, sortie propre:

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

Il répertorie tous vos fichiers ignorés, remplace chaque ligne de sortie par une ligne entre guillemets pour gérer les chemins avec des espaces à l'intérieur et passe tout git rm -r --cachedpour supprimer les chemins / fichiers / répertoires de l'index.

David Hernandez
la source
3
Excellente solution! Fonctionne parfaitement et se sent plus correct que de supprimer tous les fichiers puis de les rajouter.
Jon Catmull
5
Moi aussi j'ai trouvé ce "plus propre". Cela peut être évident, mais le simple fait d'exécuter la première partie git ls-files --ignored --exclude-standardvous permet tout d'abord de comprendre / vérifier quels fichiers votre nouveau .gitignoreva exclure / supprimer, avant de continuer et d'exécuter la finale git rm.
JonBrave
Soyez conscient, échoue sur les noms de fichiers avec certains caractères "méchants", par exemple \n. J'ai publié ma solution pour répondre à cela.
JonBrave
3
Une autre mise en garde: lors de l'extraction, cela entraînera la suppression du fichier dans les répertoires de travail des autres, non?
LarsH
essayé, mais n'a pas fonctionné pour moi: sed: 1: "s/.*/": unterminated substitute in regular expressiondans une commande de branche de filtre sur un dépôt avec des espaces. (Semblait travailler en dehors de la branche de filtre cependant). J'ai plutôt utilisé la réponsegit ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached de @ JonBrave .
goofology
71

retirez-le, engagez-vous, puis réinstallez-le. Cela a fonctionné pour moi dans le passé. Il existe probablement un moyen plus «gitteux» d'accomplir cela.

Joel Hooks
la source
2
Cela a très bien fonctionné si vous voulez ignorer un tas de fichiers qui n'étaient pas ignorés auparavant. Bien que, comme vous l'avez dit, il existe probablement une meilleure façon de procéder.
Oskar Persson
C'est exactement ce que j'ai fait. Déplacez simplement les fichiers dans un dossier en dehors de git, puis faites "git add.", "Git commit". (Cela a supprimé les fichiers) puis ajoutez le gitignore, en référençant les fichiers / dossiers, validez à nouveau pour ajouter le fichier gitignore à git, puis copiez / reculez dans les dossiers, et ils doivent être ignorés. NB: il semblerait que les fichiers ont été supprimés de GIT, donc les supprimeraient probablement d'autres extractions / extractions, comme mentionné dans les solutions ci-dessus, mais puisque vous en faites des copies au départ, ce n'est pas autant un problème à mon humble avis. faites simplement savoir au reste de l'équipe ...
Del
C'est le moyen le plus simple de se débarrasser des dossiers mal validés.
Martlark
2
Semble être le seul moyen, que je peux voir. C'est un énorme bogue (pas une «fonctionnalité») dans git qui, dès que vous ajoutez un fichier / dossier à .gitignore, il n'ignore pas simplement ce fichier à partir de ce moment - pour toujours - partout.
JosephK
Cela a fonctionné après les avoir ajoutés, puis après les avoir ajoutés à .gitignore
hanzolo
66

Si vous ne pouvez pas git rmun fichier suivi parce que d'autres personnes pourraient en avoir besoin (avertissement, même si vous git rm --cached , quand quelqu'un d'autre obtient cette modification, leurs fichiers seront supprimés dans leur système de fichiers). Celles-ci sont souvent effectuées en raison de remplacements de fichiers de configuration, d'informations d'identification d'authentification, etc. Veuillez consulter https://gist.github.com/1423106 pour savoir comment les gens ont résolu le problème.

Résumer:

  • Demandez à votre application de rechercher un fichier ignoré config-overide.ini et utilisez-le sur le fichier config.ini validé (ou alternativement, recherchez ~ / .config / myapp.ini ou $ MYCONFIGFILE)
  • Validez le fichier config-sample.ini et ignorez le fichier config.ini, ayez un script ou similaire copiez le fichier si nécessaire si nécessaire.
  • Essayez d'utiliser gitattributes clean / smudge magic pour appliquer et supprimer les modifications pour vous, par exemple, tachez le fichier de configuration comme une extraction d'une branche alternative et nettoyez le fichier de configuration comme une extraction de HEAD. C'est un truc délicat, je ne le recommande pas à l'utilisateur novice.
  • Conservez le fichier de configuration sur une branche de déploiement qui lui est dédiée et qui n'est jamais fusionnée avec master. Lorsque vous souhaitez déployer / compiler / tester, vous fusionnez avec cette branche et obtenez ce fichier. C'est essentiellement l'approche smudge / clean, sauf en utilisant des politiques de fusion humaine et des modules extra-git.
  • Anti-recommentation: n'utilisez pas assumer inchangé, cela ne se terminera qu'en larmes (car avoir du mensonge pour lui-même entraînera de mauvaises choses, comme votre changement étant perdu pour toujours).
Seth Robertson
la source
7
git ne supprimerait pas le fichier s'il était sale au moment de la suppression. Et si ce n'est pas sale, la récupération du fichier serait aussi facile que git checkout <oldref> -- <filename>- mais alors il serait extrait et ignoré.
amenthes
Concernant votre dernière note (à propos --assume-unchanged): soit c'est du fret culte et doit être écarté, soit vous pouvez expliquer pourquoi (dont je suis convaincu) et ça devient utile.
RomainValeri
58

Utilisez ceci lorsque:

1. Vous souhaitez déceler un grand nombre de fichiers, ou

2. Vous avez mis à jour votre fichier gitignore

Lien source: http://www.codeblocq.com/2016/01/Untrack-files-already-added-to-git-repository-based-on-gitignore/

Supposons que vous ayez déjà ajouté / validé certains fichiers dans votre référentiel git et que vous les ajoutiez ensuite à votre .gitignore; ces fichiers seront toujours présents dans votre index de référentiel. Cet article, nous verrons comment s'en débarrasser.

Étape 1: validez toutes vos modifications

Avant de continuer, assurez-vous que toutes vos modifications sont validées, y compris votre fichier .gitignore.

Étape 2: supprimez tout du référentiel

Pour effacer votre repo, utilisez:

git rm -r --cached .
  • rm est la commande remove
  • -r permettra la suppression récursive
  • –Cached ne supprimera que les fichiers de l'index. Vos fichiers seront toujours là.

La rmcommande peut être impitoyable. Si vous souhaitez essayer ce qu'il fait au préalable, ajoutez le -nou--dry-run drapeau pour tester les choses.

Étape 3: tout ajouter à nouveau

git add .

Étape 4: Valider

git commit -m ".gitignore fix"

Votre référentiel est propre :)

Poussez les modifications sur votre télécommande pour voir également les modifications.

Dheeraj Bhaskar
la source
1
Il ne supprimera pas les fichiers du référentiel distant? Que se passe-t-il si je souhaite conserver les fichiers dans le référentiel local et le référentiel distant mais que git les "oublie"?
Avishay28
AFAIK, cela ne supprimera pas les fichiers de l'historique car nous n'utilisons aucune commande de modification de l'historique (corrigez-moi si je me trompe). Cela ajoute seulement un nouveau commit en supprimant les fichiers ignorés dans gitignore de git. Ces fichiers seront là dans les engagements historiques
Dheeraj Bhaskar
49

J'ai accompli cela en utilisant git filter-branch . La commande exacte que j'ai utilisée provient de la page de manuel:

AVERTISSEMENT : cela supprimera le fichier de tout votre historique

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

Cette commande recréera l'intégralité de l'historique des validations, s'exécutant git rmavant chaque validation et supprimera ainsi le fichier spécifié. N'oubliez pas de le sauvegarder avant d'exécuter la commande car il sera perdu.

drrlvn
la source
9
Cela modifiera tous les ID de validation, interrompant ainsi les fusions des branches en dehors de votre copie du référentiel.
bdonlan
19
AVERTISSEMENT: cela supprimera le fichier de votre historique complet. C'est ce que je cherchais cependant, pour supprimer un fichier complètement inutile et surdimensionné (sortie qui n'aurait jamais dû être validé) qui a été validé il y a longtemps dans l'historique des versions.
zebediah49
48

Ce qui n'a pas fonctionné pour moi

(Sous Linux), je voulais utiliser les messages ici suggérant l' ls-files --ignored --exclude-standard | xargs git rm -r --cachedapproche. Cependant, (certains) des fichiers à supprimer avaient une nouvelle ligne / LF / incorporée \ndans leurs noms. Aucune des solutions:

git ls-files --ignored --exclude-standard | xargs -d"\n" git rm --cached
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

faire face à cette situation (obtenir des erreurs sur les fichiers introuvables).

Je vous propose donc

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git commit -am "Remove ignored files"

Cela utilise l' -zargument de ls-files et l' -0argument de xargs pour répondre correctement / en toute sécurité aux caractères "méchants" dans les noms de fichiers.

Dans la page de manuel git-ls-files (1) , il indique:

Lorsque l'option -z n'est pas utilisée, les caractères TAB, LF et barre oblique inversée dans les noms de chemin sont représentés respectivement par \ t, \ n et \\.

Je pense donc que ma solution est nécessaire si les noms de fichiers contiennent l'un de ces caractères.

JonBrave
la source
1
Pour moi, c'est la meilleure solution. Il a de bien meilleures performances qu'un git add .. Il contient également les meilleures améliorations de certains commentaires ci-dessus.
Nils-o-mat
Pouvez-vous ajouter ensuite thSoft git commit -am "Remove ignored files"à votre réponse? Vos réponses combinées m'ont fait traverser les choses: j
kando
Je ne comprends pas le but de git commit -a. Pour moi, git rm --cachedaffectez exactement l'index donc pas besoin de mettre en scène les fichiers après ...
Jean Paul
23
  1. Mettez à jour votre .gitignorefichier - par exemple, ajoutez un dossier vers lequel vous ne souhaitez pas effectuer le suivi .gitignore.

  2. git rm -r --cached .- Supprimez tous les fichiers suivis, y compris ceux voulus et indésirables. Votre code sera en sécurité tant que vous avez enregistré localement.

  3. git add .- Tous les fichiers seront ajoutés à nouveau, à l'exception de ceux dans .gitignore.


Pointe du chapeau à @AkiraYamamoto pour nous avoir pointés dans la bonne direction.

Chen_Wayne
la source
1
Que diriez-vous de voter en raison du fait qu'il ne fonctionnera pas réellement car vous avez besoin d'un -r pour exécuter rm de manière récursive de toute façon :) (Quelqu'un n'a pas copié correctement)
Aran Mulholland
1
Avertissement: cette technique n'entraîne pas en fait git à ignorer le fichier, mais à la place, git supprime le fichier. Cela signifie que si vous utilisez cette solution, chaque fois que quelqu'un d'autre fait un git pull, le fichier sera supprimé. Il n'est donc pas ignoré. Voir la solution suggérant git update-index --assume-inchanged à la place pour une solution à la question d'origine.
2017
16

Je pense que git ne peut pas totalement oublier le fichier à cause de sa conception ( section "Instantanés, pas les différences" ).

Ce problème est absent, par exemple, lors de l'utilisation de CVS. CVS stocke les informations sous forme de liste de modifications basées sur des fichiers. Les informations pour CVS sont un ensemble de fichiers et les modifications apportées à chaque fichier au fil du temps.

Mais dans Git chaque fois que vous validez ou enregistrez l'état de votre projet, il prend essentiellement une photo de ce que tous vos fichiers à ce moment et stocke une référence à cet instantané. Donc, si vous avez ajouté un fichier une fois, il sera toujours présent dans cet instantané.

Ces 2 articles m'ont été utiles:

git assumer-inchangé vs skip-worktree et Comment ignorer les modifications dans les fichiers suivis avec Git

Sur cette base, je fais ce qui suit, si le fichier est déjà suivi:

git update-index --skip-worktree <file>

À partir de ce moment, toutes les modifications locales de ce fichier seront ignorées et ne seront pas transmises à distance. Si le fichier est modifié à distance, un conflit se produira, quand git pull. Stash ne fonctionnera pas. Pour le résoudre, copiez le contenu du fichier dans un endroit sûr et procédez comme suit:

git update-index --no-skip-worktree <file>
git stash
git pull 

Le contenu du fichier sera remplacé par le contenu distant. Collez vos modifications d'un endroit sûr dans un fichier et recommencez:

git update-index --skip-worktree <file>

Si tout le monde, qui travaille avec le projet, effectuera git update-index --skip-worktree <file> , les problèmes avec pulldevraient être absents. Cette solution est OK pour les fichiers de configuration, lorsque chaque développeur a sa propre configuration de projet.

Il n'est pas très pratique de le faire à chaque fois, lorsque le fichier a été modifié à distance, mais peut le protéger contre l'écrasement par le contenu distant.

Boolean_Type
la source
16

Suivez les étapes suivantes en série, tout ira bien.

1. supprimez les fichiers ajoutés par erreur du répertoire / stockage . Vous pouvez utiliser la commande "rm -r" (pour linux) ou les supprimer en parcourant les répertoires. Ou déplacez-les vers un autre emplacement sur votre PC. [Vous devrez peut-être fermer l'IDE si vous exécutez pour déplacer / supprimer ]

2. ajoutez les fichiers / répertoires au gitignorefichier maintenant et enregistrez-le.

3. supprimez- les maintenant du cache git en utilisant ces commandes (s'il y a plus d'un répertoire, supprimez-les un par un en émettant plusieurs fois cette commande)

git rm -r --cached path-to-those-files

4.Maintenant, faites un commit et un push , utilisez ces commandes. Cela supprimera ces fichiers de git remote et empêchera git de suivre ces fichiers.

git add .
git commit -m "removed unnecessary files from git"
git push origin
Shamsul Arefin Sajib
la source
13

La réponse copier / coller est git rm --cached -r .; git add .; git status

Cette commande ignorera les fichiers qui ont déjà été validés dans un référentiel Git mais nous les avons maintenant ajoutés .gitignore.

youhans
la source
9

La réponse de Matt Fear était à mon humble avis la plus efficace. Ce qui suit est juste un script PowerShell pour ceux dans Windows pour supprimer uniquement les fichiers de leur dépôt git qui correspondent à leur liste d'exclusion.

# Get files matching exclusionsfrom .gitignore
# Excluding comments and empty lines
$ignoreFiles =  gc .gitignore | ?{$_ -notmatch  "#"} |  ?{$_ -match  "\S"} | % {
                    $ignore = "*" + $_ + "*"
                    (gci -r -i $ignore).FullName
                }
$ignoreFiles = $ignoreFiles| ?{$_ -match  "\S"}

# Remove each of these file from Git 
$ignoreFiles | % { git rm $_}

git add .
Ameer Deen
la source
Dans quelle situation cette liste de fichiers ne sera-t-elle pas égale au --cached récursif?
John Zabroski
8

Déplacez ou copiez le fichier vers un emplacement sûr pour ne pas le perdre. Ensuite, générez le fichier et validez. Le fichier s'affichera toujours si vous revenez à l'une de ces validations antérieures ou à une autre branche où il n'a pas été supprimé. Cependant, dans tous les commits futurs, vous ne verrez plus le fichier. Si le fichier est dans git ignore, vous pouvez le déplacer dans le dossier et git ne le verra pas.

Apreche
la source
34
git rm --cachedsupprimera le fichier de l'index sans le supprimer du disque, donc pas besoin de le déplacer / le copier
bdonlan
7

L'utilisation de la git rm --cachedcommande ne répond pas à la question d'origine:

Comment forcez-vous gità oublier complètement [un fichier]?

En fait, cette solution entraînera la suppression du fichier dans toutes les autres instances du référentiel lors de l'exécution d'ungit pull !

La bonne façon de forcer git à oublier un fichier est documentée par GitHub ici .

Je recommande de lire la documentation, mais en gros:

git fetch --all
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch full/path/to/file' --prune-empty --tag-name-filter cat -- --all
git push origin --force --all
git push origin --force --tags
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

il suffit de le remplacer full/path/to/filepar le chemin complet du fichier. Assurez-vous d'avoir ajouté le fichier à votre.gitignore .

Vous devrez également autoriser (temporairement) les poussées non rapides vers votre référentiel , car vous modifiez votre historique git.

Skeets
la source
5

Le BFG est spécialement conçu pour supprimer les données indésirables comme les gros fichiers ou les mots de passe des dépôts Git, il a donc un indicateur simple qui supprimera tous les gros fichiers historiques (pas dans votre commit actuel): '--strip-blobs- plus grand que'

$ java -jar bfg.jar --strip-blobs-bigger-than 100M

Si vous souhaitez spécifier des fichiers par nom, vous pouvez également le faire:

$ java -jar bfg.jar --delete-files *.mp4

Le BFG est 10-1000x plus rapide que git filter-branch, et généralement beaucoup plus facile à utiliser - consultez les instructions d'utilisation complètes et les exemples pour plus de détails.

Source: https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html

Meir Gerenstadt
la source
5

Si vous ne voulez pas utiliser la CLI et que vous travaillez sur Windows, une solution très simple consiste à utiliser TortoiseGit , il a l'action "Supprimer (garder local)" dans le menu qui fonctionne bien.

Peter T.
la source
5

J'ai aimé la réponse de JonBrave mais j'ai des répertoires de travail assez salissants qui valident -a me fait un peu peur, alors voici ce que j'ai fait:

git config --global alias.exclude-ignored '! git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached && git ls-files -z --ignored --exclude-standard | xargs -0 git stage && git stage .gitignore && git commit -m "nouveau gitignore et supprimer les fichiers ignorés de l'index" '

le décomposer:

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached 
git ls-files -z --ignored --exclude-standard | xargs -0 git stage 
git stage .gitignore 
git commit -m "new gitignore and remove ignored files from index"
  • supprimer les fichiers ignorés de l'index
  • stage .gitignore et les fichiers que vous venez de supprimer
  • commettre
Jay Irvine
la source
4

Ce n'est plus un problème dans le dernier git (v2.17.1 au moment de la rédaction).

Le .gitignoreignore enfin les fichiers suivis mais supprimés. Vous pouvez le tester par vous-même en exécutant le script suivant. La git statusdéclaration finale devrait signaler "rien à engager".

# Create empty repo
mkdir gitignore-test
cd gitignore-test
git init

# Create a file and commit it
echo "hello" > file
git add file
git commit -m initial

# Add the file to gitignore and commit
echo "file" > .gitignore
git add .gitignore
git commit -m gitignore

# Remove the file and commit
git rm file
git commit -m "removed file"

# Reintroduce the file and check status.
# .gitignore is now respected - status reports "nothing to commit".
echo "hello" > file
git status
Lloyd
la source
Je suis content que Git fasse maintenant ça. Cependant, l'OP demandait de ne pas suivre les modifications des fichiers présents dans le .gitignore, pas les fichiers supprimés affichant toujours un état.
mrturtle
2

En cas d'engagement déjà engagé DS_Store:

find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch

Ignorez-les en:

echo ".DS_Store" >> ~/.gitignore_global
echo "._.DS_Store" >> ~/.gitignore_global
echo "**/.DS_Store" >> ~/.gitignore_global
echo "**/._.DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global

Enfin, faites un commit!


la source
2

Surtout pour les fichiers basés sur IDE, j'utilise ceci:

Par exemple, le slnx.sqlite, je viens de m'en débarrasser complètement comme suit:

git rm {PATH_OF_THE_FILE}/slnx.sqlite -f
git commit -m "remove slnx.sqlite"

Gardez simplement à l'esprit que certains de ces fichiers stockent des paramètres utilisateur locaux et des préférences pour les projets (comme les fichiers que vous avez ouverts). Ainsi, chaque fois que vous naviguez ou effectuez des modifications dans votre IDE, ce fichier est modifié et, par conséquent, il le vérifie et s'affiche comme s'il y a des modifications non validées.

curiousBoy
la source
2

La réponse acceptée ne "fait pas oublier à Git " un fichier ... "(historiquement). Cela ne fait que git ignorer le fichier dans le présent / futur.

Cette méthode permet git oublier complètement les fichiers ignorés ( passé / présent / futur), mais ne pas rien de suppression du répertoire de travail (même lorsqu'il est tiré de nouveau à distance).

Cette méthode nécessite l'utilisation de /.git/info/exclude(préféré) OU un préexistant .gitignore dans tous les commits qui ont des fichiers à ignorer / oublier. 1

Toutes les méthodes d'application de git ignorent le comportement après coup réécrivent efficacement l'historique et ont donc des ramifications importantes pour tout dépôt public / partagé / collaboratif qui pourrait être extrait après ce processus. 2

Conseil général: commencez par un dépôt propre - tout est validé, rien en attente dans le répertoire de travail ou l'index, et faites une sauvegarde !

De plus, l' historique des commentaires / révisions de cette réponse ( et l'historique des révisions de cette question ) peut être utile / éclairant.

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch

git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch

git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#Commit to prevent working directory data loss!
#this commit will be automatically deleted by the --prune-empty flag in the following command
#this command must be run on each branch

git commit -m "ignored index"

#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits.  If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command

git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all

#List all still-existing files that are now ignored properly
#if this command returns nothing, it's time to restore from backup and start over
#this command must be run on each branch

git ls-files --other --ignored --exclude-standard

Enfin, suivez le reste de ce guide GitHub (à partir de l'étape 6) qui comprend des avertissements / informations importants sur les commandes ci-dessous .

git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

Les autres développeurs qui tirent du référentiel distant maintenant modifié devraient faire une sauvegarde, puis:

#fetch modified remote

git fetch --all

#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed

git reset FETCH_HEAD

Notes de bas de page

1 Puisqu'il /.git/info/excludepeut être appliqué à toutes les validations historiques en utilisant les instructions ci-dessus, les détails sur la manière d'obtenir un .gitignorefichier dans les validations historiques qui en ont besoin dépassent le cadre de cette réponse. Je voulais qu'un correct .gitignoresoit dans le commit racine, comme si c'était la première chose que je faisais. D'autres peuvent ne pas s'en soucier car /.git/info/excludepeuvent accomplir la même chose, peu importe où il .gitignoreexiste dans l'historique de validation, et la réécriture claire de l'histoire est un sujet très délicat, même en étant conscient des ramifications .

FWIW, les méthodes potentielles peuvent inclure git rebaseou git filter-branchcopier un externe .gitignore dans chaque commit, comme les réponses à cette question

2 L' application du comportement ignorer git après coup en validant les résultats d'une git rm --cachedcommande autonome peut entraîner une suppression de fichier nouvellement ignorée lors de futures extractions de la télécommande forcée. L' --prune-emptyindicateur dans la git filter-branchcommande suivante évite ce problème en supprimant automatiquement la validation d'index uniquement "supprimer tous les fichiers ignorés" précédente. La réécriture de l'historique de git modifie également les hachages de validation, ce qui fera des ravages sur les futurs tirages des dépôts publics / partagés / collaboratifs. Veuillez bien comprendre les ramifications avant de procéder à un tel dépôt. Ce guide GitHub spécifie les éléments suivants:

Dites à vos collaborateurs de rebaser , et non de fusionner, toutes les branches qu'ils ont créées à partir de votre ancien historique (corrompu) du référentiel. Un commit de fusion pourrait réintroduire une partie ou la totalité de l'historique entaché que vous venez de prendre la peine de purger.

Des solutions alternatives qui n'affectent pas le dépôt à distance sont git update-index --assume-unchanged </path/file>ou git update-index --skip-worktree <file>, dont des exemples peuvent être trouvés ici .

goofologie
la source
0

Si quelqu'un a du mal sur Windows et que vous voulez ignorer le dossier entier, «cd» pour le «dossier» souhaité et faites «Git Bash Here».

git ls-files -z | xargs -0 git update-index --assume-unchanged
RajVimalC
la source
0

Dans mon cas ici, j'avais plusieurs fichiers .lock dans plusieurs répertoires que je devais supprimer. J'ai exécuté ce qui suit et cela a fonctionné sans avoir à aller dans chaque répertoire pour les supprimer:

git rm -r --cached **/*.lock

Faire cela est allé dans chaque dossier sous la «racine» de l'endroit où j'étais et a exclu tous les fichiers qui correspondaient au modèle.

J'espère que cela aide les autres!

DC.Skells
la source