I can tell you what I do. This may or may not be the best option for you, depending on what programs you have configuration files for, how much variation there is between machines, and how much effort you prefer to put in writing portable configuration files versus duplicating maintenance between per-version or per-site files.
All my configuration files are under version control. I use CVS, which is perfectly sufficient for the task, but if you're starting now (as opposed to back when Linus didn't believe in version control), you may use another version control system. Version control is always good, regardless of whether you have multiple checkouts. To synchronize a modification between sites, I commit and update.
I strive to write portable files. For example, my .zshrc
is supposed to be compatible with all versions since 2.5 (however this is a bit of a stretch: I haven't tested it recently, and the last time I loaded it on a machine with zsh 2.5, it was really slow). This means I have a lot of things like if type someprogram >/dev/null 2>/dev/null
and case $ZSH_VERSION
(when I can't avoid it). The same goes for other programs whose configuration file is an interpreted language (bash, Emacs, Vim, Fvwm, Sawfish, …). I didn't want to maintain separate versions of these files, so every version-dependent definition is under a conditional statement. If you want to keep the hassle down (at the expense of supporting fewer combinations), you can do something like
case $ZSH_VERSION in
[5-9]*|4.[2-9].*) . ~/.zshrc-42;;
4.[01].*) . ~/.zshrc-40;;
3.1.[6789]) . ~/.zshrc-31;;
*) . ~/.zshrc-2;;
esac
But there are other system dependencies (e.g. the version of ls
so you know whether to alias it to gnuls --color -b
or ls --color -b
or colorls -G
or ls -Fb
or …). Splitting everything into separate files gets tiresome pretty quickly.
I keep a per-site directory with per-site settings, which are loaded by the main file. For example, my .zshrc
contains the lines
if [ -r ~/Here/lib/shell/local.zshrc ]; then
. ~/Here/lib/shell/local.zshrc
fi
Here
is a symbolic link to a directory containing site-specific configuration files. It doesn't exist on sites that I haven't customized. The local .zshrc
typically contains aliases, directory aliases and the like. Most sites have a local .profile
that define a few environment variables. All site-specific configurations are under the same version control system (checking them all out is just a few kB more).
A few files are automatically generated by a makefile. For example, I have a script to generate ~/.ssh/config
from a common list of hosts (aliases and options for machines reachable from anywhere) plus a site-specific list of hosts (for machines reachable only within a network).
Best Answer
Keep the files under version control. This has multiple benefits, including facilitating keeping files synchronized (commit on one machine, update on the others) and keeping a history of changes (so you can easily find out what broke a program that worked last month).
I use CVS and synchronize the repositories with Unison or sneakernet, but that's because I've been doing this since a time before widely-available distributed version control. Anyone starting now should use a proper distributed version control tool, such as bazaar, darcs, git, mercurial, ...
Managing files that need to differ between machines is always a bit of a pain. If the configuration language allows conditionals, use them. Otherwise, if there is an include mechanism, use it to split the configuration file into a machine-dependent part and a shared part. Keep all the machine-dependent parts in a separate directory (something like
~/.local/NAME/
) which is always referred to through a symbolic link (~/.here
->local/NAME
on each machine). I have a few files that are generated by a script in the shared part from parameters kept in the machine-specific part; this precludes modifying these files indirectly through a GUI configuration interface. Avoid configuring things in/etc
, it's harder to synchronize between machines.