Git for Configuration Files
From Shaun Rowland Wiki
I’ve decided to start using Git for revision control when editing configuration files on UNIX. Git is especially good for this since the repository is in the working directory. This avoids situations like the following example:
[rowland@www conf]$ ls httpd.conf* httpd.conf httpd.conf-new httpd.conf.both httpd.conf-3-24-2004 httpd.conf-rowland httpd.conf.default httpd.conf-3-27-2002 httpd.conf.021607 httpd.conf.ssl httpd.conf-9-18-2001 httpd.conf.bak
As you can see, my name is on the end of one of those files, so I can’t complain too much. I’ve decided to do the right thing on new replacement systems instead.
My first problem was that I did not want to track all files in /etc, but I wanted to track a number of them - the ones I’d be editing of course. To solve this, I created an /etc/git directory and hard linked files from /etc into /etc/git for tracking. Note that you have to be weary of editors that will break hard links, like emacs.[1] I finally found a use for hard links! Sure, I’ve used them once or twice before, but this is a real use. I feel more complete now. How useful this trick ends up being depends on how many repositories I end up tracking. This might be all right for me, but confusing for others. I might just track all of /etc instead at some point.
I did some quick searching for a post-commit script similar to what I’ve used with Subversion to email commits, but I did not find much. I was in a hurry though, so I came up with something quick:
REPOSITORY="Description [/path/to/repo/dir]"
RECIPIENT="revision-control@example.com"
LINES=5000
/usr/sbin/sendmail -t <<EOF
$(git log --patch-with-stat --no-color --max-count=1 --pretty=format:"From: %ce%nSubject: [$HOSTNAME] %s%nDate: %cD%nTo: $RECIPIENT%n%nHostname: $HOSTNAME%nRepository: $REPOSITORY%nAuthor: %an <%ae>%nCommitter: %cn <%ce>%nParent: %P%nCommit: %H%nOutput truncated at $LINES lines.%n%n%b%n%n" |head -$LINES)
EOF
exit 0
That seems to meet my needs for now at least. Git is great for tracking changes to configuration files, and with this post-commit script, I now get somewhat useful email when changes happen.
I also came up with a post-receive version that can be used in shared remote Git repositories:
read -a input
OLD_VALUE=${input[0]}
NEW_VALUE=${input[1]}
REF_NAME=${input[2]}
REPOSITORY="Description [/path/to/repo/dir]"
RECIPIENT="revision-control@example.com"
LINES=5000
if [ $OLD_VALUE == "0000000000000000000000000000000000000000" ] || [ $NEW_VALUE == "0000000000000000000000000000000000000000" ]; then
/usr/sbin/sendmail -t <<EOF
From: git@example.com
Subject: $REPOSITORY
To: $RECIPIENT
A non-commit change was made on:
Reference Name: $REF_NAME
EOF
else
/usr/sbin/sendmail -t <<EOF
$(git log $OLD_VALUE..$NEW_VALUE --patch-with-stat --no-color --pretty=format:"From: %ce%nSubject: [$HOSTNAME] %s%nDate: %cD%nTo: $RECIPIENT%n%nHostname: $HOSTNAME%nRepository: $REPOSITORY%nAuthor: %an <%ae>%nCommitter: %cn <%ce>%nParent: %P%nCommit: %H%nReference Name: $REF_NAME%nOutput truncated at $LINES lines.%n%n%b%n%n" |head -$LINES)
EOF
fi
exit 0
Notes
- ↑ Vi will not break hard links by default, and surely you are using vi for editing configuration files, right?