Edit – although of course I love to have some readership for this post, I should say that you might want to check out this cooler solution instead: etckeeper is a package that was designed to do all the stuff I’m describing here… thanks to Daniel for his comment!
Well, to be absolutely honest, it was the second thing I did. The first thing after installing was fixing the wifi drivers. But straight away after that, I set up version control on the configuration files in /etc. Basically, that stops you from making a mess out of your configuration files. Sounds good?
Thanks to the guys at Canonical (who are also the ones backing Ubuntu), version control has become easier than ever: with Bazaar it is so easy to set up that I basically have version control for anything I’m working on nowadays. If you know about revision control already, probably you see the use of it and could skip the rest of this post… or you could stick around and see how effortless things become with Bazaar (bzr).
Edit – probably superfluous, but just another word of warning: don’t do anything just because I did. There’s a lot of sudoing going on below here, so you could do damage to your system. Don’t trust a random blogger. Read the man pages, read the online documentation.
Before I show how to set it up, let’s see how you’d use it. Every time you’ve made significant changes to /etc (let’s say you installed new packages, or created new users, or reconfigured your acpi-support settings, or anything), you create a “checkpoint”, or in version control lingo: you commit a revision. That could be as simple as two lines in a terminal (and I’m sure you can get a GUI for this too):
cd /etc sudo bzr commit -m "short comment on what you've done"
Well, actually, if you had installed new software you might not know what had changed. So you’d have a few more lines:
cd /etc sudo bzr status #tells you which files are new or have been changed sudo bzr diff filename #tells which lines in "filename" were just added/removed sudo bzr add . #puts any new files under version control sudo bzr commit -m "short comment on what you've done" #sets a checkpoint
Still, not too scary, I’d say? Later, you can review what you changed before:
cd /etc sudo bzr log #shows comments, date, and version numbers of committed revisions
You can go back to any revision now, say e.g. to number 3:
cd /etc sudo bzr revert -r 3 #sends state of /etc back to revision 3
Here’s the real kicker though: you can also revert changes within specific files, between any two revisions. That is, you don’t have to send the whole file back to it’s old state, bzr can just remove/reinsert the lines that you’re interested in and leave all other (later!) changes to the file intact. This is what really makes revision control more powerful than plain and simple file backup.
An example: you’ve changed /etc/X11/xorg.conf to use the proprietary fglrx video driver. You removed all the tweaks you had put in before for the open-source driver. This change was part of revision 4. Some days later, you put in all kinds of tweaks for your synaptics touchpad. That was revision 9. Yet some time later, you added wacom tablet settings. Revision 15. But now, you decide you want your open-source driver back… If you’d restore the backup, you’d lose your synaptics and wacom settings. With bzr, this is how you do it:
cd /etc sudo bzr merge -r 4..3 ./X11/xorg.conf sudo bzr diff #shows the changes, just to check if it was ok sudo bzr commit -m "went back to the open-source driver by undoing rev4"
That’s it. Really. Effortless. All your fancy tweaks for the video driver have now been put back in place, but the changes you made for the input devices have not been removed. (In case you’re interested: the bzr user guide calls this reverse cherry-picking).
Stating the obvious
This is of course useful for a lot more things than just /etc. Revision control works well on anything that looks like text. Have a look at the files in your ~/.gconf directory: they’re in xml format. Now if you tweak the looks of your Gnome desktop and applications, bzr can track what changes you made. And restore older settings later.
Setting it up
Installing bzr is of course as easy as
sudo aptitude install bzr
…or apt-get if you want to be old-skool ;) Now, I had a look around the net to see if anyone else used bzr for this, and found this – frankly, that’s pretty much what I’m about to type up here. I’ll give it a spin of my own but I’ll also skip a few bits here, like how to back up your bzr repository and how to send yourself messages in case you forgot to commit your changes to the repository – so see russel.rucus.net for those parts.
Bringing everything in /etc under version control is as simple as
cd /etc sudo bzr init #creates a version control repository under /etc/.bzr sudo chmod go-rwx .bzr #only root may see it sudo bzr add . #adds everything in /etc to it sudo bzr commit -m "freshly installed state of Hardy"
You need to use superuser permissions here because you’re not allowed to read everything as a normal user (think /etc/shadow and such). As you’re storing those sensitive files in the bzr repository, you don’t want anyone to read it, hence the chmod. As a result of this chmod, you will now always need to use sudo – otherwise bzr cant access .bzr/.
Now, bzr by default is set to skip some files, for example something like apt/sources.list~ is a previous version of apt/sources.list and will get skipped because of the tilde. Of course you want to check that bzr doesn’t accidentally skip anything important, so
sudo bzr ignored #prints all skipped files
If you see any file there that you did want to add, you can add it by explicitly typing
sudo bzr add sources.list~ #you don't want that, but it's an example
Basically, your /etc directory is now under version control. You can very easily check for changes with
cd /etc sudo bzr status
as I said before, and if you’ve installed new software and new files appear in /etc, you can now do
sudo bzr add . #adds all the new files sudo bzr commit -m "installed awesome new package"
A few more things you should note
There may be some files that you actually don’t want or need to put version control on. You can create an ignore-list for those files, so that bzr will skip them when you say “add .”. Guess what the command is?
sudo bzr ignore ./mtab #bzr will ignore mtab from now on
This actually creates a file /etc/.bzrignore with “./mtab” in it. The leading ./ means you only want to ignore /etc/mtab, not any mtab found somewhere under /etc.
Now, you actually already added mtab in the section above, so there’s no point ignoring it now – it’s already under version control. To take something out of revision control:
sudo bzr remove --keep mtab
Here, –keep means that you don’t want to delete mtab. Otherwise, bzr might think you want to get rid of the file, while you just want to take it out of revision control. So far, I have done this on four files: ./mtab, ./adjtime, ./resolv.conf, ./ld.so.cache – these are all files that get generated automatically and are changed by the system (on a standard Hardy install, resolv.conf gets changed by network-manager). After running “remove –keep” on them, you’ve got something to commit again: removing is a change, too.
Second thing. If you installed bzr and immediately used it as superuser, something will be funny in your home directory now: the ~/.bazaar directory will be owned by root. If you use bzr on other things later on, without sudoing, that will generate errors. So
sudo chown -R yourname:yourname ~/.bazaar
In this .bazaar directory you will find a file .bazaar/ignore which specifies the patterns that are ignored by default (like the tilde). Change it as you like.
Finally, if you want to be more verbose in your commit messages, you can leave out the -m and the comment, and bzr will open an editor for you. Type your essay, then save and exit to complete the commit. But by now I’m really just telling you stuff you could read in the Bazaar User Guide – an excellent piece of documentation. Have lots of fun!
PS: if you’re a control freak like me (hey, you’ve read this dreadful piece all the way down), you may also like the previous post on strictly separating repo and non-repo software.