Git: comment supprimer un fichier de l'index sans supprimer des fichiers de n'importe quel référentiel

Lorsque vous utilisez

git rm --cached myfile

Il ne supprime pas du système de fichiers local, ce qui est le but. Mais si vous avez déjà versionné et validé le fichier, l'avez poussé vers un référentiel central et l'avez tiré dans un autre référentiel avant d'utiliser la commande, il supprimera le fichier de ce système.

Existe-t-il un moyen de supprimer simplement le fichier de la gestion des versions sans le supprimer de n'importe quel système de fichiers?

Edit: clarifié, j'espère.

145
demandé sur Nick Volynkin 2010-04-09 05:52:07

7 réponses

Je ne pense pas qu'un commit Git puisse enregistrer une intention comme "arrêtez de suivre ce fichier, mais ne le supprimez pas".

La mise en œuvre d'une telle intention nécessitera une intervention en dehors de Git dans tous les dépôts qui fusionnent (ou rebasent sur) un commit qui supprime le fichier.


Enregistrer une copie, appliquer la suppression, restaurer

La chose la plus simple à faire est probablement de dire à vos utilisateurs en aval d'enregistrer une copie du fichier, de retirer votre suppression, puis de restaurer le fichier. Si ils tirent via rebase et "transportent" des modifications au fichier, ils obtiendront des conflits. Pour résoudre de tels conflits, utilisez git rm foo.conf && git rebase --continue (si le commit en conflit a des modifications en plus de celles du fichier supprimé) ou git rebase --skip (si le commit en conflit a seulement changé pour le fichier supprimé).

Restaurer le fichier comme non suivi après avoir tiré un Commit qui le supprime

Si ils ont déjà tiré la suppression de commettre, ils peuvent toujours récupérer la version précédente du fichier avec git montrer:

git show @{1}:foo.conf >foo.conf

Ou avec git Commander (par Commentaire de William Pursell; mais n'oubliez pas de le retirer de l'index!):

git checkout @{1} -- foo.conf && git rm --cached foo.conf

S'ils ont pris d'autres mesures depuis la suppression (ou s'ils tirent avec rebase dans une tête détachée), ils peuvent avoir besoin d'autre chose que @{1}. Ils pourraient utiliser git log -g pour trouver le commit juste avant de retirer votre suppression.


Dans un commentaire, vous mentionnez que le fichier que vous voulez "untrack, but keep" est une sorte de fichier de configuration requis pour exécuter le logiciel (directement à partir d'un référentiel).

Conservez le fichier par défaut et activez-le manuellement/automatiquement

S'il n'est pas complètement inacceptable de continuer à maintenir le contenu du fichier de configuration dans le référentiel, vous pouvez renommer le fichier suivi de (par exemple) foo.conf à foo.conf.default, puis demander à vos utilisateurs de cp foo.conf.default foo.conf après avoir appliqué la validation de renommage. Ou, si les utilisateurs utilisez déjà une partie existante du référentiel (par exemple un script ou un autre programme configuré par le contenu du référentiel (par exemple Makefile ou similaire)) pour lancer / déployer votre logiciel, vous pouvez intégrer un mécanisme par défaut dans le processus de lancement/déploiement:

test -f foo.conf || test -f foo.conf.default &&
    cp foo.conf.default foo.conf

Avec un tel mécanisme par défaut en place, les utilisateurs devraient être en mesure de tirer un commit qui renomme foo.conf à foo.conf.default sans avoir à faire de travail supplémentaire. En outre, vous évitez d'avoir à copier manuellement un fichier de configuration si vous faire des installations/dépôts supplémentaires à l'avenir.

Réécrire L'Historique Nécessite Une Intervention Manuelle De Toute Façon ...

Si il est inacceptable de maintenir le contenu du référentiel, alors vous voudrez probablement de se débarrasser complètement de l'histoire avec quelque chose comme git filter-branch --index-filter …. Cela revient à réécrire l'historique, ce qui nécessitera une intervention manuelle pour chaque branche / référentiel (voir la section" Récupération de Rebase en amont " dans le git rebase page de manuel ). Le traitement spécial requis pour votre fichier de configuration serait juste une autre étape que l'on doit effectuer lors de la récupération de la réécriture:

  1. enregistrez une copie du fichier de configuration.
  2. récupérer de la réécriture.
  3. restaurez le fichier de configuration.

Ignorez-le pour éviter la récurrence

Quelle que soit la méthode que vous utilisez, vous voudrez probablement inclure le nom de fichier de configuration dans un fichier .gitignore dans le référentiel que personne ne peut par inadvertance git add foo.conf à nouveau (c'est possible, mais nécessite -f/--force). Si vous avez plus d'un fichier de configuration, vous pouvez envisager de les "déplacer" tous dans un seul répertoire et d'ignorer le tout (en "déplaçant", je veux dire en changeant où le programme s'attend à trouver ses fichiers de configuration, et en amenant les utilisateurs (ou le mécanisme de lancement/déploiement) à copier/déplacer les fichiers vers leur nouvel emplacement; vous ne vous serez en ignorant).

105
répondu Chris Johnsen 2010-04-10 07:52:26

A eu le même problème Cette semaine quand j'ai accidentellement commis, puis j'ai essayé de supprimer un fichier de construction d'un référentiel partagé, et ceci:

Http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html

A bien fonctionné pour moi et n'a pas été mentionné jusqu'à présent.

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

Pour supprimer le fichier qui vous intéresse du contrôle de version, utilisez toutes les autres commandes comme d'habitude.

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

Si vous avez toujours voulu le remettre en place.

Modifier: veuillez consulter les commentaires de Chris Johnsen et KPM, cela ne fonctionne que localement et le fichier reste sous contrôle de version pour les autres utilisateurs s'ils ne le font pas aussi. La réponse acceptée donne des méthodes plus complètes / correctes pour y faire face. Aussi quelques notes du lien si vous utilisez cette méthode:

Évidemment, il y a quelques mises en garde qui entrent en jeu avec cela. Si vous git ajoutez le fichier directement, il sera ajouté à l'index. La fusion d'un commit avec ce drapeau provoquera le fusionner pour échouer gracieusement afin que vous puissiez le manipuler manuellement.

84
répondu Tom Power 2015-03-03 08:11:12

Pour supprimer le fichier de l'index, utilisez:

git reset myfile

Cela ne devrait pas affecter votre copie locale ou de quelqu'un d'autre.

29
répondu Armand 2010-04-09 12:51:48

Après avoir fait la commande git rm --cached, essayez d'ajouter myfile au fichier .gitignore (Créez-en un s'il n'existe pas). Cela devrait dire à git d'ignorer myfile.

Le fichier .gitignore est versionné, vous devrez donc le valider et le pousser vers le référentiel distant.

13
répondu awgy 2010-04-09 02:03:36
  1. git rm --cached remove_file
  2. Ajouter un fichier à gitignore
  3. git add .gitignore
  4. git commit -m "Excluding"
  5. amusez-vous;)
9
répondu Анастасия Ермолик 2017-02-09 18:08:02

Ma solution est de tirer sur l'autre copie de travail, puis faire:

git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1

Qui dit obtenir tous les chemins de fichier dans le dernier commentaire, et les vérifier à partir du parent de HEAD. Le travail est accompli.

1
répondu Tom Viner 2012-01-05 16:24:22

Les solutions ci-dessus fonctionnent bien dans la plupart des cas. Cependant, si vous devez également supprimer toutes les traces de ce fichier (c'est-à-dire les données sensibles telles que les mots de passe), vous voudrez également le supprimer de tout votre historique de validation, car le fichier pourrait toujours être récupéré à partir de là.

Voici une solution qui supprime toutes les traces du fichier de tout votre historique de validation, comme si elle n'avait jamais existé, tout en conservant le fichier en place sur votre système.

Https://help.github.com/articles/remove-sensitive-data/

Vous pouvez passer à l'étape 3 Si vous êtes dans votre dépôt Git local et que vous n'avez pas besoin d'effectuer une opération à sec. Dans mon cas, je n'avais besoin que des étapes 3 et 6, comme je l'avais déjà créé mon .fichier gitignore, et était dans le référentiel sur lequel je voulais travailler.

Pour voir vos modifications, vous devrez peut-être aller à la racine GitHub de votre référentiel et actualiser la page. Ensuite, naviguez à travers les liens pour arriver à un ancien commit qui avait autrefois le fichier, pour voir qu'il a maintenant été supprimé. Pour moi, simplement rafraîchir l'ancienne page de validation n'a pas montré le changement.

Il avait l'air intimidant au début, mais vraiment, était facile et travaillé comme un charme ! :-)

0
répondu SherylHohman 2015-12-11 20:00:03