Git for Configuration Files

From Shaun Rowland Wiki

Jump to: navigation, search

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:

#!/bin/bash

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:

#!/bin/bash

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

  1. Vi will not break hard links by default, and surely you are using vi for editing configuration files, right?

System Administration

Personal tools