April 15, 2011

Weekend Project: Using git to Manage Config Files


If you've been using Linux a while, you probably have some finely tuned configuration files for Bash, Vim, Emacs, or other applications. Keeping track of those files manually, and copying them to other machines when you set up new systems, can be a pain. Take control of your config files on Linux by using git to track changes and move your configs to new systems.

Typically I use Dropbox to sync my files for work, but Dropbox isn't a good solution for files under /etc or .config type files under your home directory. You could whip up some hacks to compensate for this, but the other problem is that Dropbox isn't a good solution when you want to pull the config files onto a new machine — and only those files.

Another solution would be to use rsync, Duplicity, or Unison. But I want to keep versions of the file — not just a single copy. So git (or another version control system) is the right answer — at least for me, and probably for quite a few other folks.

The other reason I chose git is because I have few opportunities to work with git, and felt like I should spend more time working with it. The side effect here is that git masters might have more efficient ways to do some of these things, but I'm mainly just trying to lay down a simple set of instructions that will work for people who aren't git experts. If you have ideas on how to improve the workflow, though, please feel free to leave comments!

Here's what we're going to cover, and the steps you'll need to take to start using git to manage your config files:

  • Setting up your SSH keys so you can use git without having to use a password.
  • Installing git on all machines you're using.
  • Creating a "bare" repository on the remote machine.
  • Creating a repository on the local machine you want to sync.
  • Adding files to the repository.
  • Committing to the repository.
  • Pushing to the remote repository.
  • Making a change and committing that.
  • Cloning the repo to a different machine.

Getting Started

First things first, you're going to need to have a machine that acts as the git repository, and be able to connect to that machine via SSH. It could be a machine on your LAN, it could be a remote machine (I use a VPS hosted by Linode, which I also use for my Website), or you could use a service like Github. You'll find some decent, fairly basic, instructions for using Github for config files — but I didn't want to depend on Github for my configuration files.

Step one is to have a SSH key and have it set up on the remote host. Use ssh-keygen -t dsa to create a DSA key, or just ssh-keygen to use the default. I don't enter a passphrase, this way you can log in just using the key with no passphrase. This does mean if someone has physical access to your machine, they have physical access to remote machines as well — be careful. If you have anything particularly sensitive in git or on your laptop(s), I'd strongly recommend encrypting your home partition. That's a bit beyond the scope of this article, of course.

Now you need to copy it to the remote host. You'll want to copy the key to ~/.ssh/authorized_keys, which you can do with ssh-copy-id
This e-mail address is being protected from spambots. You need JavaScript enabled to view it
if you're on Ubuntu/Debian based systems. Other distros may not have that script, so you'll need to scp the ~/.ssh/id_dsa.pub or ~/.ssh/id_rsa.pub to the remote machine and copy it to ~/.ssh/authorized_keys. Note that you should use cp id_rsa.pub >> ~/.ssh/authorized_keys to append the file rather than overwrite it, assuming you have other keys.

Naturally you're going to need to have git installed on the systems as well. For Ubuntu/Debian users this should be the git-core package.

Creating Repositories

Now it's time to create the repositories. We're going to start with the remote repository, then we'll start with the repository on the local machine and then add files. To create the remote repository, SSH to the machine and then create a directory to hold the repo and create a "bare" repository:


mkdir project
cd project
git init --bare

Simple, yes? Now on your local machine you're going to set up the repo for your configuration files and add a few files to be tracked by git. Now, normally if you were working on a project you'd create a directory on the local machine and start from scratch — but here, you want to track existing files. For the purposes of this article, I'm going to use my .vimrc and .vim directory.


git config --global user.name "Your Name"
git config --global user.email 
 This e-mail address is being protected from spambots. You need JavaScript enabled to view it
cd ~/
git add .vimrc
git add .vim
git commit -m 'First Commit'
git remote add origin user@remote:project
git push origin master


Let's walk through the commands here. I used git's config command to set my name and email address. Strictly speaking, this isn't necessary, but it's a good idea.

Then I cd'ed to my home directory, and then added my .vimrc and .vim directory. You can also add any other config files you want to track. Note that adding a directory will track the entire directory. What about everything else under your home directory? Git will not track those files.

Naturally, you'll replace "user" with your username and "remote" with the name of the remote machine, and "project" with the name you've given your project.

Copying Configs and Making Changes

Next I make the first commit, and then added the remote repository, then pushed the commit to the bare repository. Now it's time to learn to make changes and to grab your config files on new machines.

Let's start with a simple change — make a one-line change to your .vimrc or another configuration file. Then go ahead and commit the change:


git commit -a -m 'Minor change in vimrc'
git push origin master


You should see something like this:


Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 318 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
 This e-mail address is being protected from spambots. You need JavaScript enabled to view it
   366a106..9bf6cdf  master -> master


Now that you've synced it, it's time to pull changes to another machine and set it up. Again — you're going to want to have your SSH key set up so that you can pull / push to your git repository without fussing with the password:


cd ~/
git init
git pull user@remote:project
git remote add origin user@remote:project


And that's it! Want to make changes? Use the same git commit and git push commands we've already used.

Note that you're not going to use git clone here, because that would give us a copy of the whole directory rather than placing the configuration files where you want them (in the home directory). You can also replicate this with your /etc directory or any other files or directories you want to manage.

Want to see what all files are currently under git's control? Use git ls-files.

If you've made a change to a config file and want to roll it back to the current version that's in your remote repository? Use git checkout filename.

Finally, you can revert to earlier states as well. You can use git log to see all your commits. You'll see something like this:


commit 9bf6cdfa61950afc5eb95d9d5b68c4bd1c9653b2
Author: Joe Brockmeier <
 This e-mail address is being protected from spambots. You need JavaScript enabled to view it
Date:   Fri Apr 15 12:14:53 2011 -0500

    minor vimrc change

commit 366a106005f73750bfa1bbfab91e6118c49df184
Author: Joe Brockmeier <
 This e-mail address is being protected from spambots. You need JavaScript enabled to view it
Date:   Fri Apr 15 11:53:03 2011 -0500

    changed vimrc


To revert to an earlier commit, run git revert rev where the "rev" is the long string after the commit line (like "366a106005f73750bfa1bbfab91e6118c49df184").


While git may not be the most end-user friendly tool, it's really not hard to become familiar with. This project doesn't begin to cover all of git's functionality. I've glossed over, for example, branching and tagging — which can be useful, but a bit beyond the scope of what I'm trying to cover here. Don't worry — we'll get those in another article.

Weekend project homework? Set up your own git repository and start managing your config files. It's a good way to quickly and easily set up new machines, and for disaster recovery.

Click Here!