Managing configuration files in your home directory on a POSIX system can be a pain when you often work on more than one machine, or when you accidentally remove or delete some useful option or file. It turns out that it’s beneficial to manage your configuration files via a version control system, which will allow you both to track the changes you make, and also to easily implement them on other machines. In this case, I’m going to show you how to do it with Git, but in principle there’s no reason most of this couldn’t work with Subversion or Mercurial.
Choosing which files to version
A good way to start is to take a look at the dot files and dot directories you have storing your carefully crafted configurations, and figure out for which of them it would be most important to track changes and to be able to rapidly deploy on remote systems. I use the following criteria:
- Compatibility: Is the configuration likely to work on all or most of
the systems on which you’re going to use it? If you’re going to check out
your cutting edge
.vimrc
file on a remote Debian Sarge machine that hasn’t been updated since 2006, you might find that a lot of it doesn’t work properly. In some cases, you can add conditionals to configuration files so that they only load the option if it’s actually available. Similarly, you might not want to copy your.bashrc
to all of your machines if you use a wide variety of them. - Transferability: Are you going to want exactly the same behaviour this
file configures on all of your remote systems? If your
.gitconfig
file includes a personal handle or outside e-mail address, it might not be appropriate for you to clone that onto your work servers, since it’ll end up in commits you do from work. - Mutability: Are you going to be the only agent that updates this configuration, or will programs change it as well, for example to store cached file references? This can make updating a pain.
- Privacy: If you’re going to put the file on GitHub or any other public repository service, does it contain private information? You probably shouldn’t put anything with API keys, SSH keys, or database credentials out in the ether.
With these criteria applied, it turns out there are configurations for three programs that I really want to be able to maintain easily across servers: my Vim configuration, my Git configuration, and my GNU Screen configuration.
Creating the repository
To start, we’ll create a directory called .dotfiles
to hold all our
configuration, and initialise it as an empty Git repository.
$ mkdir .dotfiles
$ cd .dotfiles
$ git init
Then we’ll copy in the configuration files we want to track, and drop symbolic links to them from where they used to be, so that the applications concerned read them correctly.
$ cd
$ mv .vim .dotfiles/vim
$ mv .vimrc .dotfiles/vimrc
$ mv .screenrc .dotfiles/screenrc
$ mv .gitconfig .dotfiles/gitconfig
$ ln -s .dotfiles/vim .vim
$ ln -s .dotfiles/vimrc .vimrc
$ ln -s .dotfiles/screenrc .screenrc
$ ln -s .dotfiles/gitconfig .gitconfig
Next, we drop into the .dotfiles
directory, add everything to the staging
area, and commit it:
$ cd .dotfiles
$ git add *
$ git commit -m "First commit of dotfiles."
And that’s it, we’ve now got all four of those files tracked in our local Git repository.
Using a remote repository
With that done, if you want to take the next step of having a central location where you can always get your configuration from any machine with an internet connection, you can set up a repository for your dot files on GitHub, with a free account. The instructions for doing this on GitHub itself are great, so just follow them for your existing repository. On my machine, the results look like this:
$ git remote add origin git@github.com:tejr/dotfiles.git
$ git push -u origin master
Note that I’m pushing using a public key setup, which you can arrange in the SSH Public Keys section of your GitHub account settings.
With this done, if you update your configuration at any time, first add and commit the changes to your local repository, and then all you need to do to update the GitHub version as well is:
$ git push
Cloning onto another machine
Having done this, when you’re working with a new machine onto which you’d like to clone your configuration, you clone the repository from GitHub, and delete any existing versions of those files in your home directory to replace them with symbolic links into your repository, like so:
$ git clone git@github.com:tejr/dotfiles.git .dotfiles
$ rm -r .vim .vimrc .screenrc .gitconfig
$ ln -s .dotfiles/vim .vim
$ ln -s .dotfiles/vimrc .vimrc
$ ln -s .dotfiles/screenrc .screenrc
$ ln -s .dotfiles/gitconfig .gitconfig
Finally, if you come back to use this machine later after you’ve tweaked these configuration files a bit and pushed them to GitHub, you can update them by just running a pull:
$ git pull
Making things easier
This ends up taking a lot of annoyances out of my day, as I know on any machine
on which I frequently work, all I need to do is drop to my .dotfiles
directory and run a git pull
to get the most recent version of my
configurations. This ends up being a lot better than manually running scp
or
rsync
calls to keep things up to date.