Comment puis-je faire en sorte que git ignore les futures révisions d'un fichier?

140

J'ai créé une version par défaut d'un fichier inclus dans un référentiel git. Il est important que lorsque quelqu'un clone le référentiel, il obtienne une copie de ce fichier. Cependant, je voudrais configurer git de sorte qu'il ignore les modifications apportées à ce fichier ultérieurement. .gitignorene fonctionne que sur les fichiers non suivis.

Ma motivation est que ce fichier contient des informations spécifiques à la machine. Je voudrais fournir des valeurs par défaut, tout en permettant aux gens d'apporter des modifications locales qui ne seront pas repoussées vers le référentiel d'origine, créant des conflits de fusion lorsque nous tirons de nouvelles modifications.

Nous sommes généralement assez paresseux et utilisons git add .beaucoup, donc je suis sûr que si je ne peux pas dire à git d'ignorer ce fichier, les modifications qui y sont apportées finiront par être validées et poussées.

Résumer,

  1. Je voudrais créer un fichier, l'appeler default_values.txtqui est ajouté à mon référentiel git et est inclus lorsque quelqu'un clone ce référentiel.
  2. git add .ne devrait pas ajouter default_values.txtau commit.
  3. Ce comportement doit être transmis à tous les clones du référentiel.
Marc
la source
1
Pouvez-vous utiliser les hooks git pour avoir un hook pré-commit qui annulerait une validation si le fichier modifié est default_values.txt (disons)?
sateesh
1
Les puristes de Git diraient de ne pas être paresseux et d'utiliser correctement la zone de préparation, c'est à cela qu'il sert.
Xint0
Les puristes de Git diraient d'utiliser des scripts smudge / clean. C'est la solution la plus maintenable.
Adam Dymitruk le
1
Xint0: vrai. mais comment empêcher d'autres personnes de s'enregistrer accidentellement?
Alan
duplication possible des fichiers de configuration spécifiques à la machine de
validation

Réponses:

115

Comme beaucoup d'autres l'ont mentionné, une bonne solution moderne est:

git update-index --skip-worktree default_values.txt

Cela ignorera les modifications apportées à ce fichier, à la fois locales et en amont, jusqu'à ce que vous décidiez de les autoriser à nouveau avec:

git update-index --no-skip-worktree default_values.txt

Vous pouvez obtenir une liste des fichiers marqués comme ignorés avec:

git ls-files -v . | grep ^S

Notez que contrairement à --skip-worktree, le --assume-unchangedstatut sera perdu une fois qu'un changement en amont est tiré.

humeur
la source
2
Si quelqu'un d'autre extrait le référentiel et modifie le fichier, les modifications apportées à son répertoire sont-elles ignorées? J'espère qu'ils devront taper --no-skip-worktreepour ajouter leurs modifications.
neaumusic
3
Ce qui est fait de leurs changements est contrôlé par eux. En d'autres termes, ils devraient définir skip-worktree sur le fichier de leur dépôt s'ils ne voulaient pas que leurs modifications soient transmises. S'il s'agit d'un fichier destiné à être envoyé à tout le monde et dont toutes les modifications ultérieures sont ignorées, tout le monde devrait suivre ces mêmes instructions.
moodboom
3
Notez que vous devrez peut-être annuler l' --skip-worktreeétat d'un fichier avant de pouvoir changer de branche, si ce même fichier est suivi dans l'autre branche.
moodboom
3
hmm, cela fonctionne ... après avoir modifié le fichier, il n'a pas été affiché git status, mais lorsque j'ai essayé de récupérer une branche différente, j'ai error: Your local changes to the following files would be overwritten by checkout: , même -f n'aide paserror: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
ykravv
1
J'ai ces alias git ignoreet git unignore.
Michael le
48

Ce que vous recherchez, c'est git update-index --assume-unchanged default_values.txt.

Consultez la documentation pour plus de détails: http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html

tamasd
la source
11
cela ne fonctionne pas. bien que cela fasse ajouter git. ignorez le fichier sur la branche locale, un clone de l'archive n'a pas ce comportement (si vous changez default_values.txt dans l'archive clonée, il sera ajouté au commit avec "git add.")
Marc
6
Oui, car vous le définissez uniquement pour le dépôt local. Vous ne pouvez pas pousser ce genre d'informations.
tamasd
8
@Indradhanush - cette solution ne satisfait pas le critère 3 - "le comportement doit être transmis à tous les clones du référentiel" - c'est pourquoi je ne l'ai pas accepté. Cela ne veut pas dire que ce n'est pas une bonne réponse.
Marc
Je n'ai jamais remarqué le 3ème critère. Parce que je ne le cherchais pas. :)
Indradhanush Gupta
3
Pour les fichiers de configuration locaux avec des paramètres d'application privée, vous voudrez probablement utiliser à la skip-worktreeplace de assume-unchangedplus d'informations stackoverflow.com/questions/13630849/…
Aaron Hoffman
22

L'approche que j'ai généralement vue est de créer un fichier avec un nom différent, par exemple: default_values_template.txt et de mettre default_values.txt dans votre .gitignore. Demandez aux utilisateurs de copier default_values_template.txt dans default_values.txt dans leurs espaces de travail locaux et d'apporter les modifications nécessaires.

Laurence Gonsalves
la source
hmmm ... peut-être que je pourrais écrire un hook pour copier automatiquement default_values_template dans default_values ​​si default_values ​​n'existe pas?
Marc
2
C'est la façon la plus courante de résoudre ce problème d'après mon expérience. C'est à peu près le chemin de moindre résistance en ce sens que cela "fonctionne juste", et vous pouvez facilement faire vérifier votre code si le fichier de configuration local existe et fournir une erreur utile si ce n'est pas le cas.
Jani Hartikainen
Je pense que la solution est en effet de faire quelque chose comme ça, de préférence avec un script exécuté chaque fois que vous tirez ou clonez. Une idée serait que tout ce qui a une extension particulière (par exemple .basefile) est copié dans un fichier avec l'extension supprimée, puis le nom du fichier est ajouté à .gitignore dans ce répertoire. Je créerais donc un fichier default_values.txt.basefile et le validerais. Je n'ai pas les côtelettes git ou perl pour faire cela, mais je vais demander à un ami qui le fait et vous dire comment cela fonctionne.
Marc
1
@AdamDymitruk: Oui, clean / smudge peut être utilisé dans ce cas, mais il est loin d'être clair que ce soit la meilleure option. Par exemple, cela rendra la tâche assez difficile si les gens veulent vraiment changer le fichier, car le nettoyage / bavure gênera. Je préférerais en fait l'approche décrite ici.
sleske
1
Je prends une réplique de git lui-même (spécifiquement git hooks) et utilise le .samplesuffixe. Donc dans votre casdefault_values.txt.sample
tir38 le
5

Jetez un œil aux scripts de smudge / clean. De cette façon, vous pouvez contrôler la version du fichier, mais quand il est extrait, vous le «maculerez» en remplaçant les données génériques / d'espace réservé par des données spécifiques à la machine dans le fichier.

Lorsque vous le validez, vous le «nettoyez» en remplaçant les informations spécifiques à la machine par des informations génériques ou génériques.

Les scripts Smudge / Clean doivent être déterministes en ce sens que les appliquer plusieurs fois, dans des ordres différents, équivaudra à simplement exécuter le dernier de la séquence.

La même chose peut être appliquée avec les mots de passe si vous devez exposer votre référentiel, mais le contenu peut contenir des informations sensibles.

Adam Dymitruk
la source
Les scripts Clean and Smudge sont-ils locaux ou font-ils partie du dépôt?
Alan
Oui. :) ... c'est-à-dire que vous pouvez partager le nettoyage des taches via le repo, mais ce n'est pas une bonne idée quand ils contiennent des données sensibles comme des mots de passe de production. Si ce n'est pas un problème, git vous oblige à activer explicitement le script. Sinon, les gens pourraient faire des choses malveillantes via github et d'autres dépôts partagés à d'autres utilisateurs.
Adam Dymitruk
J'ai besoin de lire un peu plus à ce sujet. Fondamentalement, je veux configurer un projet qui a une valeur par défaut user.jsonqui doit être écrasée avec les creds de chaque développeur, mais je ne veux pas que le développeur vérifie accidentellement ses creds.
Alan
Je chercherais des scripts d'exemple de smudge propres sur Google. Voyez ce qui se passe. De plus, sautez sur la salle git irc sur freenode. Vous obtiendrez de l'aide immédiatement.
Adam Dymitruk
3

J'ai résolu ce problème en définissant le filtre "propre" pour simplement trouver le contenu du fichier dans l'index.

git show :path/to/myfile devrait simplement imprimer le contenu de l'index pour le fichier spécifié, afin que nous puissions l'utiliser dans un script pour remplacer la copie de travail par la copie intacte dans l'index:

#! /bin/sh

git show :$1

Définissez cela comme le filtre "propre" pour le fichier concerné (en supposant que vous l'avez mis dans "discard_changes"):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

Malheureusement, je ne peux pas trouver un moyen de rendre cela généralisable à plusieurs fichiers, car il n'y a aucun moyen de savoir quel fichier nous traitons à partir du script propre. Bien sûr, rien ne vous empêche d'ajouter une règle de filtrage différente pour chaque fichier, mais c'est un peu brouillon.

CD Haddon.
la source
1

J'ai trouvé une solution qui fonctionne pour mon équipe. Nous partageons nos githooks via des liens symboliques et après avoir ajouté un fichier modèle à git, j'ai ajouté un hook de pré-commit qui vérifie si le fichier modèle a été modifié et si oui, je git reset -- templatefile.txt. Si c'est le seul fichier modifié, j'annule également la validation.

fruitcoder
la source
-1

Je suggère d'examiner les sous-modules. Si vous placez les fichiers spécifiques à la machine dans un sous-module, git add devrait l'ignorer.

Ivanpro
la source
c'est une bonne idée, mais je dois aussi mettre le référentiel de fichier unique sur le serveur git, ce qui est loin d'être optimal, uniquement parce que nous utilisons github et que nous avons un nombre limité de référentiels.
Marc
@Marc jetez un œil à Visual Studio Team Services, aux projets privés gratuits illimités et aux référentiels git. Tableaux Kanban, suivi des éléments de travail et des bogues, associez les enregistrements aux éléments de travail, gérez les sprints si vous êtes en mêlée ou dans d'autres types de projets. En plus de cela, il dispose d'excellents outils de construction pour construire sur plusieurs plates-formes, trop de choses à mentionner qui sont toutes gratuites. Certaines personnes le critiquent parce que c'est Microsoft, mais il dépasse largement ce que github a à offrir en termes d'outils en dehors du simple hébergement de référentiel. Il y a des limites à ce que vous pouvez faire gratuitement mais je les dépasse rarement.
Aran Mulholland
@Marc une autre chose que je trouve vraiment pratique à ce sujet est que je peux créer autant de comptes que je veux, donc si j'écris un projet pour un client qui veut posséder le contrôle de code source, je peux créer un compte, utilisez-le pour planifier, concevoir et exécuter le projet et lorsque j'ai terminé, je peux transmettre la propriété du compte au client.
Aran Mulholland