Comment arrêter le suivi et ignorer les modifications apportées à un fichier dans Git?

1731

J'ai cloné un projet qui inclut des .csprojfichiers. Je n'ai pas besoin que mes csprojfichiers locaux soient suivis par Git (ou affichés lors de la création d'un correctif), mais ils sont clairement nécessaires dans le projet.

J'ai ajouté *.csprojà mon LOCAL .gitignore, mais les fichiers sont déjà dans le repo.

Lorsque je tape git status, cela montre mes modifications csprojauxquelles je ne suis pas intéressé par le suivi ou la soumission de correctifs.

Comment puis-je supprimer le "suivi" de ces fichiers de mon référentiel personnel (mais les conserver dans la source pour que je puisse les utiliser) afin de ne pas voir les modifications lorsque je fais un statut (ou crée un patch)?

Existe-t-il une manière correcte / canonique de gérer cette situation?

Joshua Ball
la source
18
Une question très utile, mais je suis curieux de savoir pourquoi vous ne voudriez pas suivre les modifications apportées au .csprojfichier, qui est très important pour tout projet. Modifications du .csproj.userfichier ou de tout autre .Publish.XMLfichier que je ne comprends absolument pas, mais je suis intrigué de savoir pourquoi vous ne voudriez pas suivre le .csproj...
Owen Blacker
7
Peut-être utilisent-ils un IDE différent?
Jarrett
3
Ironiquement, je suis venu à ce fil parce que je cherche à supprimer les fichiers .suo d'un dépôt mais à les conserver localement. Pour la postérité, le développement .Net vous oblige à conserver les fichiers .csproj dans le référentiel et ces modifications doivent toujours être suivies, sauf si vous souhaitez ressentir la colère des autres développeurs sur votre projet. En cas de doute, jetez un œil au dépôt de fichiers gitignore sur GitHub: github.com/github/gitignore/blob/master/VisualStudio.gitignore
longda
1
@Cupcake, la question à laquelle vous avez lié a été écrite 15 jours après celle-ci? Peut-être en avez-vous un autre en tête?
stephenmurdoch
Les questions canoniques de @marflar ne doivent pas nécessairement être les plus anciennes, juste les meilleures . Celui

Réponses:

2129

Il suffit de faire appel git rm --cachedà chacun des fichiers que vous souhaitez supprimer du contrôle de révision. Tant que vos modèles locaux d'ignorance sont corrects, vous ne verrez pas ces fichiers inclus dans la sortie de l'état git.

Notez que cette solution supprime les fichiers du référentiel, donc tous les développeurs devraient conserver leurs propres copies locales (non contrôlées par les révisions) du fichier

Pour empêcher git de détecter les changements dans ces fichiers, vous devez également utiliser cette commande:

git update-index --assume-unchanged [path]

Ce que vous voulez probablement faire: (ci-dessous @Ryan Taylor réponse )

  1. C'est pour dire à git que vous voulez votre propre version indépendante du fichier ou du dossier. Par exemple, vous ne voulez pas écraser (ou supprimer) les fichiers de configuration de production / transfert.

git update-index --skip-worktree <path-name>

La réponse complète est ici dans cette URL: http://source.kohlerville.com/2009/02/untrack-files-in-git/

anthony
la source
187
"git rm --cached <file>" supprimerait <file> du contrôle de version, tout en le conservant dans le référentiel de travail. Que ce soit ce que vous voulez ...
Jakub Narębski
51
Mais lorsque d'autres tireront le référentiel, leur propre fichier * .csproj sera-t-il supprimé? Parce que si nous voulons que le fichier ne soit pas suivi, mais pas supprimé.
FMaz008
23
Si vous essayez de supprimer TOUS les fichiers d'un répertoire, combinez-le avec git ls-files: git ls-files | xargs git rm --cached- qui supprimera tout de l'index git dans un répertoire donné sans supprimer les fichiers réels.
Marco
129
git rm --cached -r <dir>fonctionne récursivement sur un dossier et tous les fichiers qu'il contient.
Chris K
41
Cela arrêtera le suivi du fichier, le conservera localement, mais le supprimera pour quiconque tire
Edward Newell
249

Si vous le faites git update-index --assume-unchanged file.csproj, git ne vérifiera pas automatiquement les modifications de file.csproj: cela les empêchera d'apparaître dans l'état git chaque fois que vous les modifierez. Ainsi, vous pouvez marquer tous vos fichiers .csproj de cette façon, bien que vous deviez en marquer manuellement tous les nouveaux que le dépôt en amont vous enverra. (Si vous les avez dans votre .gitignoreou .git/info/exclude, ceux que vous créez seront ignorés)

Je ne suis pas tout à fait sûr de ce que sont les fichiers .csproj ... s'ils correspondent à des configurations IDE (similaires aux fichiers .eclipse et .classpath d'Eclipse), je suggère qu'ils ne devraient tout simplement jamais être contrôlés par la source à tout. D'un autre côté, s'ils font partie du système de construction (comme Makefiles), alors ils devraient clairement --- et un moyen de récupérer les modifications locales facultatives (par exemple à partir d'un local.csproj à la config.mk) serait utile : divise l'accumulation en parties globales et remplacements locaux.

araqnid
la source
8
csproj est un fichier de projet C #, qui garde la trace des fichiers inclus dans votre projet et d'autres configurations, il DOIT être contrôlé par la source pour que le projet fonctionne
SparK
4
C'est la seule bonne réponse ici! J'utilise @araqnids answer depuis des années et cela fonctionne exactement comme demandé pour résoudre ce problème.
NHDaly
Quelle est la signification du préfixe «fichier» dans l'argument de la commande? Pourquoi n'est-ce pas juste .csproj?
GreenAsJade
1
Existe-t-il un moyen de détecter que cela a été fait pour un fichier ou pour quels fichiers cela a été fait dans un dépôt? Je suis un peu nerveux d'oublier que j'ai fait cela, puis de me demander pourquoi ce fichier n'est pas mis à jour plus tard!
GreenAsJade
4
@GreenAsJade: git ls-files -vaffichera les fichiers supposés inchangés avec un indicateur en minuscules (par exemple hau lieu de d'habitude Hpour les fichiers mis en cache).
Amadan
238

Il y a 3 options, vous voulez probablement # 3

1. Cela gardera le fichier local pour vous, mais le supprimera pour toute autre personne quand ils tireront.

git rm --cached <file-name> ou git rm -r --cached <folder-name>

2. C'est pour l'optimisation, comme un dossier avec un grand nombre de fichiers, par exemple des SDK qui ne changeront probablement jamais. Il dit à git d'arrêter de vérifier cet énorme dossier à chaque fois pour les modifications, localement, car il n'en aura pas. L' assume-unchangedindex sera réinitialisé et les fichiers seront écrasés s'il y a des modifications en amont du fichier / dossier (lorsque vous tirez).

git update-index --assume-unchanged <path-name>

3. C'est pour dire à git que vous voulez votre propre version indépendante du fichier ou du dossier. Par exemple, vous ne voulez pas écraser (ou supprimer) les fichiers de configuration de production / transfert.

git update-index --skip-worktree <path-name>

Il est important de savoir que git update-index cela ne se propagera pas avec git, et chaque utilisateur devra l'exécuter indépendamment.

Ryan Taylor
la source
8
Cette réponse est la plus complète - elle propose différentes solutions avec les ramifications de chacune. Le cas spécifique avec lequel je travaille a un mot de passe intégré dans un fichier de configuration. Je souhaite propager un fichier modèle puis ajouter le mot de passe à ma copie. La copie avec le mot de passe doit être ignorée et non écrasée.
bmacnaughton
1
Comment puis-je vérifier, dans ma section locale, quels fichiers s'appliquent pour «assumer-inchangé» ou «sauter-worktree»?
Supawat Pusavanno
3
@SupawatPusavanno pour voir quels fichiers vous avez précédemment sélectionnés pour supposer inchangés ou ignorer worktree regardez cette réponse stackoverflow.com/questions/42363881/… - il utilise grepetgit ls-files
Ryan Taylor
1
Très bonne réponse. Mais git lève une erreur lorsque j'essaie de passer à une autre branche: erreur: "Vos modifications locales aux fichiers suivants seraient écrasées par la caisse ....." et la solution est de cacher les modifications avant de basculer et de les retirer lorsque vous revenez à la succursale.
PhantomReference
@RyanTaylor: J'ai essayé de supposer inchangé en premier (ne fonctionnait pas) et de sauter la commande worktree (ne fonctionnait pas), lorsque je vérifie avec le statut git les fichiers ne montrent pas que la commande a fonctionné. Mais quand je récupère le code à partir de git origin repo it gives me error that your local changes would be overwrittendans ces 2 fichiers, cela signifie que ce n'est pas un non-suivi, n'est-ce pas?
NeverGiveUp161
152

Il s'agit d'un processus en deux étapes:

  1. Supprimez le suivi des fichiers / dossiers - mais conservez-les sur le disque - en utilisant

    git rm --cached 
    

    Maintenant, ils n'apparaissent pas comme "modifiés", mais apparaissent toujours comme

        untracked files in  git status -u  
    
  2. Ajoutez-les à .gitignore

rjha94
la source
56
Non, cela supprimera le fichier du suivi, le conservera localement, mais entraînera sa suppression pour quiconque tire .
Edward Newell du
1
Dans mon cas, j'ai accidentellement ajouté un dossier dont je ne voulais pas le suivi, c'est donc ce dont j'avais besoin.
Sonny
4
Oui, c'est en effet la mauvaise réponse à la question posée - mais c'est probablement la bonne réponse pour la plupart des gens qui trouvent cette question dans les résultats de recherche (comme moi).
Andrew Spencer
95

La réponse acceptée ne fonctionnait toujours pas pour moi

j'ai utilisé

git rm -r --cached.

git add.

git commit -m "correction de .gitignore"

Trouvé la réponse d' ici

Buddhika Hasthanayake
la source
Ce lien est très utile, en particulier pour supprimer récursivement tous les fichiers du .gitignore
rmcsharry
9
Je suis revenu ici 3 fois, j'espère que je pourrai me souvenir avant la prochaine fois!
Harry Bosh
Le commentaire de @Edward Newell comme dans la réponse ci - dessus s'applique également ici: "cela supprimera le fichier du suivi, le conservera localement, mais le supprimera pour quiconque tire ".
ToJo
47

Vous avez oublié votre .gitignore?

Si vous avez tout le projet localement mais avez oublié d'ajouter git ignore et que vous suivez maintenant certains fichiers inutiles, utilisez cette commande pour tout supprimer

git rm --cached -r .

assurez-vous d'être à la racine du projet.

Ensuite, vous pouvez faire l'habituel

Ajouter

git add .

Commettre

git commit -m 'removed all and added with git ignore'

Pousser

git push origin master

Conclusion

J'espère que cela aide les personnes qui doivent apporter des modifications à leur .gitignoreou tout oublier ensemble.

  • Il supprime tout le cache
  • Regarde votre .gitignore
  • Ajoute les fichiers que vous souhaitez suivre
  • Pousse à votre repo
Joe Lloyd
la source
4
Lorsque vous parlez de supprimer ou d'ajouter, vous oubliez de dire quand et où. Supprimer de la liste des pistes? Depuis le référentiel? Depuis l'espace du projet local? Retrait à la traction? Au commit? À la poussée? Hélas, tous les auteurs ici ont le même problème.
Gangnus
3
@Gangnus Je pense que personne n'a `` clarifié '' le point que vous essayez de faire valoir, car il est tout à fait évident que le fichier n'est pas réellement supprimé du disque ou du référentiel. Cette réponse spécifie l'ordre chronologique des commandes. Ce n'est pas mystérieux ou mal expliqué comme le suggère votre commentaire.
Anthony
Le commentaire de @Edward Newell comme dans la réponse ci - dessus s'applique également ici: "cela supprimera le fichier du suivi, le conservera localement, mais le supprimera pour quiconque tire ".
ToJo
26

Comme indiqué dans d'autres réponses, la réponse sélectionnée est incorrecte.

La réponse à une autre question suggère que ce pourrait être un saut de travail qui serait nécessaire.

git update-index --skip-worktree <file>
the_new_mr
la source
2
Non, pas vraiment: --skip-worktreeest utilisé pour conserver le fichier dans le référentiel mais arrêter de suivre ses modifications . Comme votre réponse le dit: --skip-worktree est utile lorsque vous demandez à git de ne jamais toucher à un fichier spécifique car les développeurs doivent le changer
Erdal G.
4
@ErdalG. Exactement. Selon la question, ils veulent ignorer toutes les modifications dans le fichier mais conserver le fichier dans le
dépôt
D'accord avec @the_new_mr, --assume-unchangedet --skip-worktreeont un effet similaire, mais leurs objectifs sont entièrement différents. Le premier sert à accélérer les performances de git en trompant git pour ne pas vérifier des fichiers particuliers , tandis que le dernier sert à ignorer les modifications futures sur des fichiers particuliers , qui conviennent à l'exécution mais aux fichiers essentiels.
Victor Wong du
22

Pour gagner du temps, les règles que vous ajoutez à votre .gitignore peuvent être utilisées pour supprimer plusieurs fichiers / dossiers, c.-à-d.

git rm --cached app/**/*.xml

ou

git rm --cached -r app/widgets/yourfolder/

etc

Peter
la source
C'est une très bonne solution car dans toute chance que vous souhaitez réparer le gitignore étape par étape
cutiko
15

Pour empêcher la surveillance d'un fichier par git

git update-index --assume-unchanged [file-path]

Et pour revenir en arrière, utilisez

git update-index --no-assume-unchanged [file-path]

Un référentiel à consulter pour des cas d'utilisation similaires https://github.com/awslabs/git-secrets

shijin
la source
1
Revenir en arrière était une bouée de sauvetage, merci!
Hamman Samuel
9

Beaucoup de gens vous conseillent d'utiliser git update-index --assume-unchanged. En effet, cela peut être une bonne solution, mais seulement à court terme.

Ce que vous voulez sans doute faire est la suivante: git update-index --skip-worktree.

(La troisième option, que vous ne voulez probablement pas, est:. git rm --cachedElle conservera votre fichier local, mais sera marquée comme supprimée du référentiel distant.)

Différence entre les deux premières options?

  • assume-unchangedest de vous permettre temporairement de masquer les modifications d'un fichier. Si vous souhaitez masquer les modifications apportées à un fichier, modifiez le fichier, puis extrayez une autre branche, vous devrez utiliser no-assume-unchangedpuis probablement cacher les modifications effectuées.
  • skip-worktree vous suivra quelle que soit la succursale que vous passez à la caisse, avec vos modifications!

Cas d'utilisation de assume-unchanged

Il suppose que ce fichier ne doit pas être modifié et vous donne une sortie plus propre lorsque vous le faites git status. Mais lorsque vous passez à une autre branche, vous devez réinitialiser l'indicateur et valider ou masquer les modifications avant. Si vous tirez avec cette option activée, vous devrez résoudre les conflits et git ne fusionnera pas automatiquement. En fait, il ne masque que les modifications ( git statusne vous montrera pas les fichiers marqués).

J'aime l'utiliser quand je veux seulement arrêter le suivi des modifications pendant un certain temps + valider un tas de fichiers ( git commit -a) liés à la même modification.

Cas d'utilisation de skip-worktree

Vous avez une classe de configuration contenant des paramètres (par exemple, y compris les mots de passe) que vos amis doivent modifier en fonction de leur configuration.

  • 1: Créez une première version de cette classe, remplissez les champs que vous pouvez remplir et laissez les autres vides / nuls.
  • 2: Validez et envoyez-le sur le serveur distant.
  • 3: git update-index --skip-worktree MySetupClass.java
  • 4: Mettez à jour votre classe de configuration avec vos propres paramètres.
  • 5: Retournez travailler sur une autre fonctionnalité.

Les modifications que vous effectuez vous suivront quelle que soit la branche. Attention: si vos amis veulent également modifier cette classe, ils doivent avoir la même configuration, sinon leurs modifications seraient poussées vers le référentiel distant. Lors de l'extraction, la version distante du fichier doit remplacer la vôtre.

PS: faites l'un ou l'autre, mais pas les deux car vous aurez des effets secondaires indésirables. Si vous souhaitez essayer un autre indicateur, vous devez d'abord désactiver ce dernier.

belka
la source
7

Pour dire à Git de ne pas suivre les modifications apportées à votre fichier / dossier local (ce qui signifie que l'état de git ne détectera pas les modifications apportées), procédez comme suit:

git update-index --skip-worktree path/to/file

Et pour demander à Git de suivre à nouveau les modifications apportées à votre version locale (afin que vous puissiez valider les modifications), procédez comme suit:

git update-index --no-skip-worktree path/to/file
Ruto Collins
la source
1

réponse d'une ligne git update-index --assume-unchanged [path]

Utilisez-le chaque fois que vous avez un fichier qui se trouve dans le référentiel central et également un référentiel local. Ce fichier ne doit pas être ajouté .gitignore. étant donné que de nouveaux changements dans le fichier sont introduits par les administrateurs système, les développeurs seniors doivent être répartis entre tous les référentiels locaux.

Meilleur exemple: fichier de configuration pour les connexions DB . Dans un référentiel central, vous aurez tous les nom d'utilisateur, mot de passe, hôte, port avec les valeurs d'un serveur de base de données de production. Mais dans le développement local, vous devez utiliser uniquement un serveur de développement local ou tout autre serveur de bases de données de développement (que votre équipe a configuré). Dans ce cas, vous souhaitez apporter des modifications au fichier de configuration, mais vous ne devez pas être validé dans le référentiel central.

Meilleur

Seenivasan
la source
0

Je suppose que vous demandez comment supprimer TOUS les fichiers dans un dossier spécifique ou le dossier bin, plutôt que de sélectionner chaque fichier séparément.

Vous pouvez utiliser cette commande:

git rm -r -f /<floder-name>\*

Assurez-vous que vous êtes dans le répertoire parent de ce répertoire.
Cette commande "supprimera" récursivement tous les fichiers qui se trouvent dans les dossiers bin / ou build /. Par le mot supprimer, je veux dire que git prétendra que ces fichiers sont "supprimés" et que ces fichiers ne seront pas suivis. Le git marque vraiment ces fichiers comme étant en mode suppression.

Assurez-vous que votre .gitignore est prêt pour les commits à venir.
Documentation: git rm

Vraj Pandya
la source
0

Le problème peut être dû à l'ordre de fonctionnement. Si vous avez d'abord modifié le .gitignore, puis git rm --cached xxx, vous devrez peut-être continuer à rencontrer ce problème.

Solution correcte:

  1. git rm --cached xxx
  2. modifié le .gitignore

Ordre invariant!

Le rechargement du .gitignore après modification!

thearyong
la source
0

Je suppose que vous essayez de supprimer un seul fichier de git tacking. pour cela, je recommanderais la commande ci-dessous.

git update-index --assume-unchanged

Ex - git update-index --assume-unchanged .gitignore .idea / compiler.xml

Pankaj Sonani
la source
0

Pour ignorer toute modification de tous les fichiers (d'un certain type) dans un répertoire, j'ai dû combiner certaines de ces approches, sinon les fichiers ont été créés s'ils n'existaient pas auparavant.

Dans la liste ci-dessous, «exclus» est le nom du répertoire dans lequel je souhaite ne pas regarder les modifications.

Tout d'abord, supprimez tous les nouveaux fichiers existants de votre cache de suivi des modifications (sans les supprimer de votre système de fichiers).

git status | grep "new file:" | cut  --complement -d " " -f1-4 | grep "^excludedir" | xargs git rm --cache

Vous pouvez faire de même avec modified:. renamed:est un peu plus compliqué, car vous devrez regarder le ->bit de post pour le nouveau nom de fichier et faire le ->bit de pré comme décrit deleted:ci-dessous.

deleted: les fichiers s'avèrent un peu plus compliqués, car vous ne semblez pas pouvoir mettre à jour-indexer un fichier qui n'existe pas sur le système local

echo .deletedfiles >> .gitignore
git status | grep "deleted:" | cut  --complement -d " " -f1-4 | grep "^excludedir" > .deletedfiles
cat .deletedfiles | xargs -d '\n' touch
cat .deletedfiles | xargs -d '\n' git add -f
cat .deletedfiles | xargs -d '\n' git update-index --assume-unchanged
cat .deletedfiles | xargs -d '\n' rm

La dernière commande dans la liste ci-dessus supprimera à nouveau les fichiers de votre système de fichiers, alors n'hésitez pas à l'omettre.

Ensuite, bloquez le suivi des modifications à partir de ce répertoire

git ls-files excludedir/ | xargs git update-index --skip-worktree
git update index --skip-worktree excludedir/
mpag
la source
0

Une approche presque sans commande a été donnée dans cette réponse :

Pour ignorer certains fichiers pour chaque dépôt local :

  1. Créez un fichier ~/.gitignore_global, par exemple par touch ~/.gitignore_globaldans votre terminal.
  2. Courez git config --global core.excludesfile ~/.gitignore_globalpour une fois.
  3. Écrivez les chemins de fichier / dir que vous souhaitez ignorer ~/.gitignore_global. par exemple modules/*.H, qui sera supposé être dans votre répertoire de travail, ie $WORK_DIR/modules/*.H.

Pour ignorer certains fichiers pour un seul dépôt local :

  1. Effectuez la troisième étape ci-dessus pour le fichier .git/info/excludedans le référentiel, c'est-à-dire écrire les chemins de fichier / dir que vous souhaitez ignorer .git/info/exclude. par exemple modules/*.C, qui sera supposé être dans votre répertoire de travail, ie $WORK_DIR/modules/*.C.
Ingénieur sans herpès
la source
0

Appliquer .gitignore au présent / futur

Cette méthode applique le comportement .gitignore standard et ne nécessite pas de spécifier manuellement les fichiers à ignorer .

Je ne peux plus utiliser --exclude-from=.gitignore: / - Voici la méthode mise à jour:

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 !

#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

#optionally add anything to the index that was previously ignored but now shouldn't be:
git add *

#commit again
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.

git commit -m "re-applied modified .gitignore"

#other devs who pull after this commit is pushed will see the  newly-.gitignored files DELETED

Si vous devez également purger les fichiers nouvellement ignorés de l'historique de validation de la branche ou si vous ne souhaitez pas que les fichiers nouvellement ignorés soient supprimés des futurs pulls , consultez cette réponse .

goofologie
la source
-1

après une longue recherche, trouvez un moyen de le faire. alias une commande git dans .gitconfig.like dans le projet de studio Android , avant que la branche de paiement ne revienne au fichier de configuration, puis ignorez-le , après que la branche de paiement utilise le sedfichier de configuration de changement dans ma configuration locale. checkoutandmodifylocalproperties = !git update-index --no-skip-worktree local.properties && git checkout local.properties && git checkout $1 && git update-index --skip-worktree local.properties && sed -i '' 's/.*sdk.dir.*/sdk.dir=\\/Users\\/run\\/Library\\/Android\\/sdk/g' local.properties && :

chinaanihchen
la source