Conseils pour mettre sous contrôle de source

77

Je souhaite placer mon répertoire personnel (~) sous contrôle de source (git, dans ce cas), car j’ai beaucoup de fichiers de paramètres (.gitconfig, .gitignore, .emacs, etc.) et les avoir à Git rendrait cela agréable pour les récupérer.

Mon ordinateur principal est mon MacBook et, de la manière dont OS X est configuré, il y a beaucoup de dossiers que je veux ignorer (Documents, Téléchargements, .ssh). Il existe également des dossiers qui utilisent déjà Git (.emacs.d).

Je pensais simplement ajouter tous ces répertoires à mon fichier .gitignore, mais cela semble assez fastidieux et pourrait éventuellement avoir des conséquences imprévues. Ma pensée suivante était de copier périodiquement les fichiers que je veux stocker dans un dossier de la maison, puis de valider ce dossier. Le problème avec ça, c'est que je dois me souvenir de les déplacer avant de m'engager.

Y a-t-il une manière propre de faire ceci?

Dan McClain
la source
Vous pouvez également créer un script en effectuant les validations des dossiers souhaités et en l’appelant via des tâches cron.
Shadok
Notez que le système de fichiers HFS + par défaut sous Mac OS X est insensible à la casse (tout en préservant la casse) et que les chemins de fichiers sont codés en UTF-8 canoniquement décomposé dans l'espace utilisateur! Pour plus d'informations, consultez: <a href=" stackoverflow.com/questions/5581857/… et le problème du tréma sous Mac OS X</a>

Réponses:

60

J'ai $HOMEsous git. La première ligne de mon fichier .gitignore est

/*

Les autres sont des modèles à ne pas ignorer à l'aide du !modificateur. Cette première ligne signifie que la valeur par défaut est d’ignorer tous les fichiers de mon répertoire personnel. Les fichiers que je veux contrôler par la version sont .gitignorecomme suit:

!/.gitignore
!/.profile
[...]

Un modèle plus délicat que j'ai est:

!/.ssh
/.ssh/*
!/.ssh/config

C’est-à-dire que je ne souhaite que la version .ssh/config- je ne veux pas que mes clés et d’autres fichiers de .ssh soient intégrés à git. Ce qui précède est la façon dont je réalise cela.

Edit: Ajout de barres obliques au début de tous les chemins. Cela fait que les modèles ignorés correspondent du haut du référentiel ($ HOME) au lieu de n'importe où. Par exemple, si !lib/était un motif (n'ignorez pas tout dans le répertoire lib) et que vous ajoutez un fichier .gitignore, auparavant, le motif ( !.gitignore) correspondait à cela. Avec la barre oblique ( !/.gitignore), elle ne correspond que .gitignoredans mon répertoire personnel et non dans les sous-répertoires.

Je n'ai pas vu de cas où cela fait une différence pratique avec ma liste Ignorer, mais cela me semble plus précis sur le plan technique.

camh
la source
1
Il me semble que la même chose peut être obtenue de manière beaucoup plus simple .
Nick Volynkin
24

Ce que je fais (avec les mêmes objectifs) est de placer mes fichiers de configuration dans un sous ~/lib- répertoire et d’avoir des liens symboliques dans mon répertoire personnel, par exemple .emacs -> lib/emacs/dot.emacs. Je ne garde que les fichiers de configuration que j'ai écrits explicitement sous contrôle de version; mon répertoire personnel contient de nombreux fichiers de points créés automatiquement qui ne sont pas sous contrôle de version. Ainsi, ~/libest sous contrôle de version, et mon répertoire personnel ne l’est pas.

J'ai un script qui crée les liens symboliques à partir des fichiers sous ~/lib. Lorsque je crée un compte sur une nouvelle machine, je la remplis en extrayant ~/libet en exécutant ce script.

Mon expérience est avec CVS, pas git, ce n'est donc pas transférable à 100%. L'une des raisons pour lesquelles je n'ai pas placé mon répertoire personnel directement sous CVS est que ~/.cvsignorecela s'appliquerait à toutes mes commandes CVS et pas seulement à mon répertoire personnel; git n'a pas ce problème. L’inconvénient de cette approche par rapport au fait que le répertoire de base est sous contrôle de version est qu’il est impossible de git statusfaire la distinction entre un fichier que vous avez explicitement décidé d’ignorer (qui serait répertorié dans le fichier ignore, donc non affiché) et un fichier. fichier sur lequel vous n’avez pas d’opinion (qui serait affiché avec un ?).

Certains fichiers doivent être différents sur des machines différentes. Je les mets dans un répertoire appelé ~/Local/SITENAME/libet crée soit des liens symboliques pour eux aussi, soit (pour les formats de fichiers qui le prennent en charge) une directive include dans le fichier sous ~/lib. J'ai aussi un lien symbolique ~/Here -> ~/Local/SITENAME. Contrairement à CVS, git est conçu pour prendre en charge des référentiels généralement similaires mais non identiques, il existe peut-être un meilleur moyen de gérer les fichiers spécifiques à une machine. Certains de mes fichiers de points ne sont en fait pas des liens symboliques, mais sont générés automatiquement à partir du contenu situé sous ~/libet ~/Here.

Gilles, arrête de faire le mal
la source
Peut-être avez-vous core.excludesfile = ~/.gitignore. Sans une telle configuration, le fichier n'est appliqué à aucun référentiel, à l'exception de celui stocké dans ~/.git(même dans ce cas, il ne s'appliquerait pas aux sous-référentiels). J'utilise core.excludesfile = ~/.git-user-excludespour éviter le conflit entre les exclus que je veux appliquer à tous mes référentiels Git (quel que soit leur emplacement) et les exclus que je veux appliqués au référentiel qui contient (une partie de) mon répertoire personnel.
Chris Johnsen
@ Chris: Je sais très peu de choses sur git. J'ai peut-être mal compris cette phrase de la gitignorepage de manuel: «Les patterns lus à partir d'un fichier .gitignore situé dans le même répertoire que le chemin ou dans n'importe quel répertoire parent (…)» s'arrêtent-ils à la racine de la commande le .gitrépertoire est)?
Gilles 'SO- arrête d'être méchant'
1
Oui, la recherche de .gitignorefichiers vers le haut est délimitée par la racine de l’arbre de travail. La phrase que vous avez citée se poursuit ainsi: «(jusqu'au sommet de l'arbre de travail)».
Chris Johnsen
@Chris: ma version de la page de manuel ne contient pas ces mots - il semble que le libellé ait été clarifié. J'ai corrigé ma réponse. Merci!
Gilles 'SO- arrête d'être méchant'
cela a été discuté dans le chat récemment
strugee
11

Nous pouvons utiliser la capacité de Git de continuer à suivre les fichiers même s’ils sont répertoriés dans .gitignore. Donc, cela suffit pour .gitignore:

$ cat .gitignore
/*

Pour chaque fichier que vous souhaitez suivre, exécutez add -f(le -fparamètre ignore ignorer à la fois dans .gitignoreet .git/info/exclude):

git add -f .gitignore
git add -f .profile
git add -f .zshrc
git add -f .ssh/config

Une fois le fichier indexé, Git suivra toutes les modifications malgré le fait que le fichier soit ignoré. La même chose fonctionne pour un répertoire, mais uniquement pour les fichiers réellement présents:

git add -f somedirname

Si vous souhaitez suivre un répertoire entier avec tous les nouveaux fichiers qui y figurent, vous pouvez en exclure .gitignorele répertoire , comme décrit dans la réponse fournie par camh :

!/somedirname

Si vous souhaitez arrêter de suivre un fichier, cette commande supprime un fichier de l'index de Git mais ne le modifie pas sur le disque dur:

git rm --cached .ssh/config
Nick Volynkin
la source
1
Je vous donnerais mes points si je pouvais. Il convient de noter que cette méthode ne peut être utilisée que pour suivre les fichiers, pas les répertoires. Si vous voulez que git dépiste tous les fichiers d'un répertoire, vous devrez toujours ignorer ce répertoire dans .gitignore. Sinon, les nouveaux fichiers de ce répertoire n'apparaîtront pas en tant que nouveaux fichiers.
camh
5

J'utilise le vieux rcspour ça.

Jetez un oeil à manpages pour ci, coet rcs. Ces sites devraient également être utiles:

J'utilise cela pour la version contrôlant mes fichiers de points, par exemple:

ci -u .*vimrc

Et si je veux les éditer:

co -l .*vimrc

Je vous recommande de créer un répertoire nommé RCSdans votre ~, vous pouvez alors le sauvegarder facilement quelque part.

polemon
la source
2
Rcs est assez démodé maintenant, et git fait tout ce que rcs fait et bien plus encore. J'avais l'habitude d'utiliser rcs pour tout ce qui était local, pour lequel je ne voulais pas avoir à mettre en place un référentiel sur un serveur, mais je suis maintenant passé à git pour ce type d'utilisation. J'ai même écrit un script qui encapsule cvs2git pour convertir une hiérarchie de répertoires existante contenant des fichiers rcs en git.
Neil Mayhew
1
Oui, je sais que c'est daté. La question était de savoir comment faire cela. Je viens de dire à ce gars comment je le fais depuis de très nombreuses années ("daté", indice, indice). Cela ne voulait pas dire que c'était la seule façon raisonnable de le faire.
polemon
5

$HOME/.conf/J'extrais mes fichiers de configuration depuis un référentiel BitBucket Mercurial. Un dépôt GitHub fonctionnerait aussi bien.

La ~/.confcaisse contient des fichiers de configuration et un script shell permettant de renseigner les liens symboliques $HOMEvers chaque fichier ~/.conf. Pour les formats de configuration qui prennent en charge l' inclusion ( .bashrc, .inputrc, .vimrc, etc.) j'inclure le ~/.conffichier plutôt que de lien vers elle, afin que je puisse faire remplacements locaux.

Pour certains fichiers de configuration, je crée un lien symbolique vers un fichier de mon dossier Dropbox et le partage via Dropbox.

Pendant quelques mois, j’ai essayé de rester $HOMEdans le contrôle de version, mais j’en avais marre de gérer les énormes listes d’ignorations, j’en avais marre de vérifier les modifications de configuration apportées par les applications en cours, et le résultat n’était même pas quelque chose que je voudrais vérifier sur un autre ordinateur. Pouvez-vous imaginer résoudre des conflits liés à ~/.gconfou ~/.config/monitors.xml, ou gérer des versions différentes d'applications de bureau?

Je trouve qu'il est plus facile de créer un lien symbolique vers ou d'inclure une liste limitée de fichiers de configuration que j'ai personnellement personnalisés et que je souhaite partager sur des machines en tant que paramètres par défaut globaux.

Graham
la source
3

Je viens juste de commencer à utiliser le script Python Dotfiles suivant, un outil pratique qui relie automatiquement les fichiers à votre intention: https://pypi.python.org/pypi/dotfiles.

trojjer
la source
1

Je pense que votre deuxième intuition d'avoir un dossier non lié sous contrôle de source est bonne.

Ajoutez simplement 2 scripts shell là-bas. Une pour copier les fichiers sous votre contrôle ~et l'autre pour collecter des fichiers ~et les recopier dans le dossier contrôlé par la source, puis validez

Alexander Pogrebnyak
la source
0

Voici un petit script ruby ​​que j'utilise pour configurer une nouvelle machine

#!/usr/bin/env ruby
# setup.rb

#list of dirs which you don't want to symlink
ignored = %w(.gitignore .gitmodules misc setup.rb readme)

current_dir = File.expand_path(Dir.pwd)
home_dir = File.expand_path("~")

links = `git ls-tree --name-only HEAD`.lines.map(&:strip).select {|x| !ignored.include?(x)  }

links.each do |link|
  link = File.join(current_dir, link)
  symlink = File.join(home_dir, File.basename(link))
  `ln -ns #{link} #{symlink}`
end
Khaja Minhajuddin
la source