g2
This is a replacement for my old 'gaf' program, to version control arbitrary config files and the like.
gaf
was a moderately complex shell script, but it was way over-engineered.
Despite that, it had some rough spots in the workflow. Hence this program --
hopefully simpler means better.
It would have been called 'gaf2' but that's 4 characters... and all useful unix commands should be 3 or less. Ideally 2.
why and what
(Note that there are many other programs like this; it's probably one of those things that everyone writes once in their life!)
Very briefly: a daily backup is a fine thing, but for a lot of "config" files, it also helps to annotate changes (i.e., "when did I make this change and why?").
For instance, all users have files like .bashrc
, .vimrc
, etc. Some users
have a further set of rc and config files unique to themselves (one example
from my laptop is the "gitolite-test" userid, and of course "root" almost
always has its own aliases and functions). Finally, the system itself has
many such files (for example the sudoers file, the sshd config, etc.)
Using g2, you can save each of these different "sets" of files into its own branch.
how
Install g2
itself, and its one dependency on each machine you wish to
use this in (just toss the two scripts in /usr/local/bin or something). Then
do this:
One-time stuff
-
create a server repo somewhere that all machines can access by some URL (like
ssh://user@host/g2.git
, etc). Let's call this$URL
. -
from any one machine, exactly once, run
g2 INIT $URL
. -
on each user+machine that wishes to use this, run once
g2 SETUP $URL
. -
on each user+machine that wishes to use a branch, run once
g2 USE $branch
.
That's it for the one-time stuff. If you add a new machine, repeat step 3 once and step 4 for each branch that machine will use. If you add a new branch, repeat step 4 on all machines which need that branch.
Regular stuff
The day-to-day work is mostly git-ish things like 'git add -f', 'git commit'
and 'git push'. If you run g2
without any arguments, you'll see the basic
commands.
Just don't use the 'master' branch for anything -- leave it alone!
Also, run g2 save $branch
if you wish to save meta-data. (Meta data is
only owner, group, and permissions; we don't do extended attributes etc.)
Doing this for system files (e.g. those in /etc) is likely to be pretty
important.
Finally, note that 'git checkout' is blocked, to prevent you losing your local changes accidentally! However, if you have a local alias for checkout, you should consider blocking that also; see "extra details" section below.
tips (and other sub-commands)
-
to enable use for the system itself (as opposed to an actual user), just
cd /
, then run the SETUP sub-command, then something likeg2 USE laptop
. It works just the same, since g2 only looks for..git
in the current directory. -
use the
sa
subcommand to get a quick status of all branches. I actually do this from root (this is of course aliased to some convenient short command in my active-aliases rc file):cd; map -1 "su --login -c 'g2 sa' %; echo" gitolite-test webuser sitaram; g2 sa; cd /; g2 sa
This runs 'sa' on the 3 most often used non-root users I have on my laptop, then root itself, then the system itself.
-
when
sa
reports any differences, usesd
to see a diff. As the help message says, sd can take any git-diff options, so for example you could say:g2 sd foo --color-words --word-diff-regex=.
-
you could also
sw
(switch) to the appropriate branch, and then run any git command:g2 sw foo g2 dcw # where my ~/.gitconfig defines dcw as 'diff --color-words'
extra details
-
The INIT sub-command sets up a master branch with one
.gitignore
file containing exactly one line:/*
Thus, by default, all files are ignored. Only files you
git add -f
will be tracked. -
The
master
branch will be used as the start point for all other branches, butmaster
itself will never be updated any more. It stays at this commit forever. -
The SETUP sub-command creates a
..git
(note two dots!) directory and a.gitignore
file in your$PWD
. -
Since git checkout is somewhat dangerous in this type of use, the script blocks it. It also blocks what I believe is the most common alias for 'checkout', which is 'co'. If you use a different alias, you may want to add it to the script to block it too.
-
All the actual files go into branches. (To illustrate, my g2 repo has a branch called "users" with files common to all users, branches called "sitaram", "gitolite-test", "root", (and a few more) for specific users, and branches called "sys-laptop", "sys-workdesktop", "root-workdesktop", "sitaram-workdesktop", and so on).
appendix a: the active-aliases script
You need to install my active-aliases script. This is a single file, so
you can also just download the script itself and put it somewhere in
$PATH
. Yes the script filename is __
(two underscores)!
(Strictly speaking, converting g2
to plain bash is almost trivial except for
the save
sub-command. Even that can be done with a little masochism.
Which, sadly, I lack).