88 votes

Transmission des fichiers de configuration spécifiques à la machine

Lorsque je développe, il arrive souvent que la base de code contienne plusieurs fichiers de configuration qui nécessitent des paramètres spécifiques à la machine. Ces fichiers sont enregistrés dans Git et d'autres développeurs les réenregistrent toujours accidentellement et cassent la configuration de quelqu'un d'autre.

Une solution simple serait de ne pas les enregistrer dans Git, ou même d'ajouter une entrée .gitignore pour eux. Cependant, je trouve qu'il est beaucoup plus élégant d'avoir des valeurs par défaut raisonnables dans le fichier que le développeur peut modifier pour répondre à ses besoins.

Existe-t-il un moyen élégant de faire en sorte que Git joue agréablement avec de tels fichiers ? J'aimerais pouvoir modifier un fichier de configuration spécifique à une machine et pouvoir ensuite exécuter "git commit -a" sans vérifier ce fichier.

1 votes

On dirait que vous avez un problème dans votre conception et dans le cerveau de vos collègues. Dites-leur de s'assurer qu'ils savent ce qu'ils commettent dans un système de contrôle de la source, sinon ils vont enregistrer de la merde que vous ne voulez pas. Aussi : Pourquoi ne pas simplement diviser le fichier, un fichier pour chaque système ?

11 votes

Je suis presque sûr que c'est un scénario assez commun ? Comment gardez-vous la trace de la configuration spécifique de la machine ? La division du fichier pour chaque système semble assez désordonnée et va à l'encontre de l'objectif d'un contrôle de version distribué : s'il est extrait sur une nouvelle machine, il ne devrait pas être nécessaire d'extraire un nouveau fichier.

1 votes

Vous pourriez au moins empêcher l'introduction des commits de rupture en utilisant un hook pre-update sur le dépôt partagé vers lequel vous poussez tous. Il peut rechercher les commits qui modifient le fichier de configuration fait par certains développeurs, ou il peut rechercher les commits touchant ce fichier qui ne mentionnent pas de mot-clé spécial dans le message.

61voto

Novelocrat Points 12126

Demandez à votre programme de lire une paire de fichiers de configuration pour ses paramètres. Tout d'abord, il doit lire un fichier config.defaults qui serait inclus dans le référentiel. Ensuite, il doit lire un config.local qui devrait être répertorié dans .gitignore

Avec cette disposition, les nouveaux paramètres apparaissent dans le fichier des valeurs par défaut et prennent effet dès qu'il est mis à jour. Ils ne varieront sur des systèmes particuliers que s'ils sont remplacés.

En guise de variante, vous pourriez avoir un simple config que vous envoyez dans le contrôle de version, et lui faire faire quelque chose comme include config.local pour introduire les valeurs spécifiques à la machine. Cela introduit un mécanisme plus général (par opposition à la politique) dans votre code, et permet par conséquent des configurations plus compliquées (si cela est souhaitable pour votre application). L'extension populaire de ceci, vue dans de nombreux logiciels libres à grande échelle, est de include conf.d qui lit la configuration de tous les fichiers d'un répertoire.

Aussi voir ma réponse à une question similaire.

0 votes

Je vais donner la réponse. Cette méthode permet d'obtenir l'effet désiré, avec le seul inconvénient qu'elle nécessite une logique supplémentaire de la part de l'application.

17voto

bhuber Points 88

Vous pouvez essayer git update-index --skip-worktree filename . Ceci indiquera à git de prétendre que les modifications locales du nom de fichier n'existent pas, ainsi git commit -a l'ignorera. Il a également l'avantage de résister git reset --hard Ainsi, vous ne perdrez pas accidentellement vos modifications locales. De plus, les fusions automatiques échoueront si le fichier est modifié en amont (sauf si la copie du répertoire de travail correspond à la copie de l'index, auquel cas elle sera automatiquement mise à jour). L'inconvénient est que la commande doit être exécutée sur toutes les machines concernées, et il est difficile de le faire automatiquement. Voir aussi git update-index --assume-unchanged pour une version subtilement différente de cette idée. Vous trouverez des détails sur les deux avec git help update-index .

0 votes

Vous pouvez trouver plus d'informations sur ces commandes dans la question Différence entre "assume-unchanged" et "skip-worktree". . De la meilleure réponse on dirait que vous voulez --skip-worktree dans ce cas.

10voto

Greg Hewgill Points 356191

Une autre approche consiste à maintenir les modifications locales des fichiers de configuration communs dans une autre branche privée. Je le fais pour certains projets qui nécessitent plusieurs modifications locales. Cette technique n'est peut-être pas applicable à toutes les situations, mais elle fonctionne pour moi dans certains cas.

Tout d'abord, je crée une nouvelle branche basée sur la branche master (dans ce cas particulier, j'utilise git-svn donc je dois commiter depuis master mais ce n'est pas très important ici) :

git checkout -b work master

Maintenant, modifiez le(s) fichier(s) de configuration si nécessaire et validez. Je mets généralement quelque chose de distinctif dans le message de commit comme "NOCOMMIT" ou "PRIVATE" (cela sera utile plus tard). A ce stade, vous pouvez travailler sur votre branche privée en utilisant votre propre fichier de configuration.

Lorsque vous voulez repousser votre travail en amont, choisissez chaque changement de votre work vers le master. J'ai un script pour aider à faire cela, qui ressemble à quelque chose comme ceci :

#!/bin/sh

BRANCH=`git branch | grep ^\\* | cut -d' ' -f2`
if [ $BRANCH != "master" ]; then
  echo "$0: Current branch is not master"
  exit 1
fi

git log --pretty=oneline work...master | grep -v NOCOMMIT: | cut -d' ' -f1 | tac | xargs -l git cherry-pick

Cette première vérification s'assure que je suis sur le master branche (vérification de l'intégrité). Ensuite, il liste chaque commit dans work filtre ceux qui mentionnent le mot-clé NOCOMMIT, inverse l'ordre, et finalement sélectionne chaque commit (en commençant par le plus ancien) dans le fichier master .

Enfin, après avoir poussé les changements dans le master en amont, je retourne à work et rebase :

git checkout work
git rebase master

Git va réappliquer chacun des commits dans le fichier work en sautant effectivement celui ou ceux qui ont déjà été appliqués dans la branche master par le biais de la cueillette de cerises. Il ne devrait vous rester que les commits locaux NOCOMMIT.

Cette technique rend le processus de poussée un peu plus long, mais elle a résolu un problème pour moi, alors j'ai pensé que je devais partager.

2 votes

Vous réalisez que vous demandez à l'ignorant qui ne pose pas de question de faire ça ? La personne qui ne fait que courir git commit -a sans se soucier du monde ?

1 votes

En suivant cette même stratégie, vous pourriez marquer le commit où vous définissez vos fichiers de configuration locaux et utiliser une combinaison de git rebase --onto y git fetch pour faire la même chose

8voto

hgmnz Points 7239

Une possibilité est d'avoir les fichiers réels dans votre .gitignore, mais de vérifier les configurations par défaut avec une extension différente. Un exemple typique pour une application Rails serait le fichier config/database.yml. Nous enregistrons config/database.yml.sample, et chaque développeur crée son propre config/database.yml qui est déjà .gitignoré.

0 votes

Oui, c'est une amélioration progressive, mais ce n'est toujours pas optimal car si la version archivée est intentionnellement modifiée, cela ne se reflète pas dans les fichiers de configuration du développeur. Un exemple de cas où cela serait utile est lorsqu'une nouvelle propriété est ajoutée, etc.

0 votes

Cela pourrait être réglé avec de bonnes notes de validation et des messages d'erreur descriptifs qui signalent qu'une propriété n'est pas définie. Il est également utile d'envoyer un courriel à votre équipe pour l'informer de ce changement.

0 votes

Pour plus d'informations sur cette solution et un excellent exemple, voir cette réponse .

1voto

Bryan Alves Points 477

Enregistrez une configuration par défaut avec une extension différente (disons .default), utilisez un lien symbolique pour lier la configuration par défaut à l'emplacement correct, ajoutez l'emplacement correct à .gitignore, et ajoutez tout ce qui est lié à la configuration à .gitignore (ainsi la seule chose qui est enregistrée est config.default).

De plus, écrivez un script d'installation rapide qui met en place les liens symboliques pour l'ensemble de votre application.

Nous avons utilisé une approche similaire dans une entreprise précédente. Le script d'installation détectait automatiquement l'environnement dans lequel vous fonctionniez (sandbox, développement, QA, production), et faisait automatiquement la bonne chose. Si vous aviez un fichier config.sandbox, et que vous vous exécutiez depuis le sandbox, il le liait (sinon il liait simplement le fichier .defaults). La procédure courante consistait à copier le fichier .defaults et à modifier les paramètres si nécessaire.

L'écriture de l'install script est plus facile que vous ne l'imaginez, et vous donne beaucoup de flexibilité.

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