179 votes

Git : Comment supprimer un fichier de l'index sans supprimer les fichiers d'un dépôt quelconque

Lorsque vous utilisez

git rm --cached myfile

il ne supprime pas le système de fichiers local, ce qui est l'objectif. Mais si vous avez déjà versionné et validé le fichier, l'avez poussé dans un dépôt central et l'avez transféré dans un autre dépôt avant d'utiliser la commande, celle-ci supprimera le fichier de ce système.

Existe-t-il un moyen de supprimer le fichier de la gestion des versions sans le supprimer du système de fichiers ?

Edit : Clarifié, j'espère.

0 votes

Peut-être pourriez-vous préciser votre cas d'utilisation. L'index est la zone d'attente pour le prochain commit, alors pourquoi voulez-vous supprimer le fichier de l'index si vous ne voulez pas le supprimer de la branche actuelle ?

1 votes

Je suis désolée. Je voulais dire que mon fichier a, pour une raison ou une autre, été commité et distribué il y a longtemps. L'objectif est maintenant de le retirer du versioning sans l'effacer des systèmes des gens. La raison pour laquelle ce problème est apparu est que j'ai accidentellement versionné un fichier de configuration. Le fichier de configuration est nécessaire, donc je ne veux pas le supprimer des systèmes étrangers.

0 votes

J'ai modifié la question pour qu'elle soit plus claire.

126voto

Chris Johnsen Points 50064

Je ne pense pas qu'un Git commit pouvez enregistrer une intention comme "arrêter le suivi de ce dossier, mais ne pas le supprimer".

La promulgation d'une telle intention, il faudra l'intervention à l'extérieur de Git dans tous les référentiels de fusion (ou de rebase sur un commit qui supprime le fichier.


Enregistrer une Copie, Appliquez Suppression, Restauration

Probablement la meilleure chose à faire est de dire à vos utilisateurs en aval pour enregistrer une copie du fichier, tirez votre suppression, puis restaurer le fichier. Si ils tirent via rebase et sont de ‘charge' des modifications au fichier, ils obtiendront des conflits. Pour résoudre de tels conflits, utilisez git rm foo.conf && git rebase --continue (si le conflit s'engager a des changements, en dehors de celles pour le fichier supprimé) ou git rebase --skip (si le conflit s'engager a seulement changé pour le fichier supprimé).

Restauration de Fichiers comme sans traces Après le tirage d'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 show:

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

Ou avec git checkout (par commentaire par William Pursell; mais souvenez-vous de la supprimer de l'index!):

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

Si ils ont pris d'autres mesures depuis tirer votre suppression (ou ils tirent avec rebase dans un décollement de la TÊTE), ils peuvent avoir besoin d'autre chose que d' @{1}. Ils pourraient utiliser git log -g trouver le commettre, juste avant qu'ils tiré votre suppression.


Dans un commentaire, vous mentionnez que le fichier que vous voulez "annuler le suivi, mais garder" est une sorte de fichier de configuration qui est nécessaire pour l'exécution du logiciel (directement d'un référentiel).

Conserver le Fichier en tant que "par Défaut" et Manuellement/Automatiquement l'Activer

Si ce n'est pas tout à fait inacceptable de continuer à maintenir le fichier de configuration est contenu dans le référentiel, vous pourriez être en mesure de renommer le fichier suivi (par exemple,) foo.conf de foo.conf.default , puis de demander à vos utilisateurs de cp foo.conf.default foo.conf après l'application de la renommer commettre. Ou, si les utilisateurs utilisent déjà certaines parties du référentiel (par exemple, un script ou un autre programme configuré par le contenu dans le référentiel (par exemple, Makefile ou similaire)) pour le lancement et le déploiement de vos logiciels, vous pouvez incorporer un mécanisme défaillant dans l'exécution du processus de déploiement:

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

Avec un tel défaut de mécanisme en place, les utilisateurs devraient être en mesure de tirer un commit qui renomme foo.conf de foo.conf.default sans avoir à faire aucun travail supplémentaire. Aussi, vous éviter d'avoir à copier manuellement un fichier de configuration si vous faire d'installations supplémentaires ou des répertoires dans l'avenir.

Réécriture De L'Histoire 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'histoire, qui nécessitent une intervention manuelle pour chaque direction/référentiel (voir "Récupération De l'Amont Rebase" dans la section de 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. Enregistrer une copie du fichier de configuration.
  2. Récupérer à partir de la réécriture.
  3. Restaurer le fichier de configuration.

L'ignorer pour Éviter les Récidives

Quelle que soit la méthode que vous utilisez, vous voudrez probablement inclure le nom du fichier de configuration dans un .gitignore fichier dans le référentiel afin que nul ne peut, par inadvertance, git add foo.conf encore (c'est possible, mais requiert -f/--force). Si vous avez plus d'un fichier de configuration, vous pourriez envisager de "mouvement" dans un seul et unique répertoire et ignorant de la chose entière (par "mouvement", je veux dire changer l'emplacement où le programme s'attend à trouver ses fichiers de configuration, et d'obtenir les utilisateurs (ou le lancement de déployer mécanisme) pour copier/déplacer les fichiers vers leur emplacement; manifestement, vous ne voulez pas git mv d'un fichier dans un répertoire que vous allez ignorer).

5 votes

Réponse incroyablement complète. Je vous remercie !

0 votes

La réponse de Tom Power, ci-dessous, semble contredire votre première phrase.

1 votes

@MikeS : L'effet de la --{,no-}assume-unchanged est purement local : son état n'est pas directement enregistré dans les commits. Il peut aider à empêcher un dépôt de livrer de nouvelles modifications au fichier, mais il ne le retire pas du contrôle de version. Si vous pouvez le définir pour tous vos dépôts pertinents, liés et non nus, alors cela peut aider votre situation, mais ce n'est pas quelque chose que vous pouvez faire. directement pousser+tirer/rebâtir dans d'autres dépôts connexes, non nus (en particulier ceux que vous ne contrôlez pas, conformément aux commentaires de clarification de l'auteur de la question initiale : voir "systèmes de personnes"/"systèmes étrangers").

92voto

Tom Power Points 636

J'ai eu le même problème cette semaine lorsque j'ai accidentellement commis, puis essayé de supprimer un fichier de construction d'un dépôt 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 normalement.

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

Si jamais vous vouliez le remettre en place.

Edit : voir 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 traiter ce problème. Vous trouverez également quelques notes sur le lien si vous utilisez cette méthode :

Il est évident qu'il y a un certain nombre de mises en garde à ce sujet. Si vous ajoutez le fichier directement par git Fusionner un commit avec ce drapeau de manière gracieuse afin que vous puissiez le gérer manuellement.

7 votes

Il ne s'agit pas d'une réponse au problème spécifique mentionné. Cela ne fonctionnera que pour votre propre dépôt local, donc chaque utilisateur doit le faire lui-même. C'est pénible.

34voto

Armand Points 4075

Pour supprimer le fichier de l'index, utilisez :

git reset mylife

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

2 votes

reset ne supprime le fichier de l'index que s'il n'est pas dans le commit HEAD actuel, sinon il ramène la version de l'index à la version HEAD actuelle.

1 votes

Peut-être ai-je mal compris la question, mais elle semble concerner la suppression d'un fichier de l'index sans affecter les commits.

0 votes

Comme l'a dit Charles, reset ne permet pas de "supprimer un fichier". Tapez git help reset pour plus d'informations.

16voto

awgy Points 3834

Après avoir fait le git rm --cached Essayez d'ajouter la commande myfile à la .gitignore (créez-en un s'il n'existe pas). Cela devrait indiquer à git d'ignorer myfile .

Les .gitignore est versionné, vous devrez donc le valider et le pousser vers le dépôt distant.

1voto

Tom Viner Points 2323

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

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

qui dit de récupérer tous les chemins de fichiers dans le dernier commentaire, et de les vérifier à partir du parent de HEAD. Le travail est fait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X