My git Hash filter


Some time ago I told you about the vigit program, to combine editing and submitting to git. This had some disadvantages, that made me search for a better solution.

I found this in the git filtering capabilities.

The major problem was that the file was modified by vigit after it was checked in to git. This means that the command

git diff

always showed differences. That was something I didn’t like at all. But I do like some version info in the file. And the git-hash as well.

I changed the vigit program in such a way that it doesn’t touch the file after the commit, but that git uses a clean and smudge filter to check the file in and out.

I also changed the short hash to the full hash, this because it is almost always needed to use the complete hash for git commands.

This is what I did:

First I created a directory ~/bin/git and added it to my path. This will now be the place to store all git related stuff.

Create a shell-script git.collaps that collapses the hash on checkin. The contents is:

#!/bin/bash
spc="$(printf "%80s", "")"
sed -e 's!\([[:space:]]*\$[H]ash::\).*\$:!\1 '"${spc:0:66}"'\$:!'

and, of course, a scripts that expands the hash on checkout (I call this git.expand)

#!/bin/bash
spc="$(printf "%80s", "")"
who=${SUDO_USER:-${LOGNAME}}
id=$(git show -s --pretty=format:"%H (${who})")
id="${id}${spc}"
sed -e 's!\([[:space:]]*\$[H]ash::\).*\$:!\1 '"${id:0:66}"'\$:!'

These two scripts need to be called when git checks files in and out, so I added the next text to the file ~/.gitconfig

[filter "git_vi"]
    smudge: git.expand
    clean: git.collaps

Now the global configuration is complete, only the last part, the connection of your repository to the git filter.

For testing it can be done like this

cd /tmp
mkdir gittest
cd gittest
git init
echo "* filter=git_vi" > .gitattributes
cat <<- @EOF > testfile
    #------------------------------------------------------------------------------#
    #                    V e r s i o n   i n f o r m a t i o n                     #
    #------------------------------------------------------------------------------#
    # $Id::                                                                     $: #
    # $Revision::                                                               $: #
    # $Author::                                                                 $: #
    # $Date::                                                                   $: #
    # $Hash::                                                                   $: #
    #------------------------------------------------------------------------------#
    #             E n d   o f   v e r s i o n   i n f o r m a t i o n              #
    #------------------------------------------------------------------------------#
@EOF

git.vi testfile

After completing the git commit message an saving it, the command

cat testfile

shows something like this

#------------------------------------------------------------------------------#
#                    V e r s i o n   i n f o r m a t i o n                     #
#------------------------------------------------------------------------------#
# $Id:: testfile 1 2009-08-10 12:57:45Z tonk                                $: #
# $Revision:: 1                                                             $: #
# $Author:: Ton Kersten <my@email-address.com>                              $: #
# $Date:: 2009-08-10 14:57:46 +0200 (Mon, 10 Aug 2009)                      $: #
# $Hash:: fac5acb249d694a3c6dfe4eca0575d30adadfeac (tonk)                   $: #
#------------------------------------------------------------------------------#
#             E n d   o f   v e r s i o n   i n f o r m a t i o n              #
#------------------------------------------------------------------------------#

and git diff shows no differences between the file on disk and the one in the repository. And that’s what I wanted.

If you want it, the git.vi program is in the files section.

Happy gitting.

Update

Miek discovered some little errors. That’s now corrected.

Of course the name of the filter in the .gitattributes and .gitconfig should be the same.

Update 2

First I used

spc='    ...   '

and that annoyed me. It’s not nice, clean programming. So I changed it to:

spc="$(printf "%80s", "")"

which is nice and better.

Old 

See also