Often I want to version control certain, usually critical, system configuration files. In the past I’ve either set this up on a directory-by-directory basis or not bothered (which results in me creating a lot of superfluous files by doing a ‘cp config_file config_file.bak_`date +%F`’ before editing).
I, with a colleague, have come up with this solution that, while not necessarily perfect, is a lot more manageable then previous alternatives I have used and has the benefits of creating a centralised repository on a given machine as well as not polluting system directories with ‘.svn’ or ‘.git’ directories. It also avoids having to play with nested repositories (i.e. directories with a ‘.git’ dir under another that also has a ‘.git’ dir), which are unlikely if you’re just version controlling /etc but more common if controlling /home/$USER. I think it’s quite neat and keeps the revision control itself away from the core system files.
The first step is to create a suitable directory to host the version control. We won’t actually be storing files here but it does need to be a “normal” repository (i.e. not a bare repository) as it does represent a working copy of the repository.
mkdir /root/vc # Calling it 'vc' for 'Version Control'
Step two is to initialise our repository:
Now, and this is the clever bit, we need to configure the repository to use ‘/’ as the base of it’s working tree (so we end up with a repository, with all it’s revision control files, in /root/vc but really the files under ‘/’ is under revision control).
I also excluded everything by default (so git does not list everything as not being controlled and we can cherry pick the files we actually care about).UPDATE: I’ve since found the config variable ‘staus.showUntrackedFiles’ (reading man-pages FTW!), which achieves the same end in a much saner manner.
git config core.worktree /
echo '*' >> .git/info/exclude
git config status.showUntrackedFiles no
…and that’s it. Just use the ‘/root/vc’ directory as a normal git repository but with any files under ‘/’. Simple, eh?
There is a drawback, however. Since I have excluded everything, files have to be added to the repository with a ‘-f’ (force) flag: UPDATE: This is no longer an issue using ‘status.showUntrackedFiles’ to disable showing untracked files by default. There maybe other issues with this approach but I’ve not spotted them in my (5 minutes!) of testing/experimentation.
git add -f /etc/ssh/sshd_config
This also applies when using ‘git add’ to stage modified files however ‘git commit -a’, which stages modified & deleted files and commits in one step, does not required ‘-f’.