Git filtering
Excellent idea Ton!
How to make a custom filter in git
to expand the string $Hash$
to
something more usefull, ala the $Id$
(which git
already supports), but
then with more info (committer, date, etc.).
Which also helped in this case was the Pro Git book which is, as of now, a must buy.
But as always is the case between Ton and me, I find his scripts too long :-) So I miekified his solution.
First we need two scripts, one to expand $Hash$ and another one to collapse it again:
git.expand
:
#!/bin/sh
id=$(git show -s --pretty=format:%h\ %ci\ ${SUDO_USER:-${LOGNAME}}%n)
sed -e 's!\([[:space:]]*\$[H]ash\)\$!\1: '"${id} "'\$!'
and git.collapse
:
#!/bin/sh
sed -e 's!\([[:space:]]*\$[H]ash\):.*\$!\1\$!'
And a final check to see if they are working:
% echo '$Hash$' | git.expand
$Hash: 8c84acf 2009-08-11 19:28:20 +0200 miekg $
Looking nice.
% echo '$Hash$' | git.expand | git.collapse
$Hash$
Wonderful - the scripts work. Now we need to set up the filtering
in git
.
Filtering⌗
As Ton also explained you need to add the filtering commands
to your global ~/.gitconfig
and then edit a .gitattributes
to
enable this on a per repository basis.
In ~/.gitconfig
add:
[filter "hash"]
smudge = git.expand
clean = git.collapse
And in your .gitattributes
add:
* filter=hash
See gitattributes(5) for more information on this.
Test⌗
Now run a little test:
% echo '$Hash$' > h
% git add h
% git commit -m'testadd' -- h
Created commit b5189fd: testadd
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 h
And, and… and…:
% cat h
$Hash$
Huh, unexpanded? Well yes, you need to remove and checkout the file for it all to work:
% rm h && git checkout -- h && cat h
$Hash: b5189fd 2009-08-11 19:50:19 +0200 miekg $
Putting it all together⌗
So now I only need a little wrapper around vi
and git
to do
all this automatically. So here is vit2
:
CODE(sh){ #!/bin/zsh
(c) Copyright Miek Gieben, 2009 Licensed under GPL v3⌗
expands $[H]ash$ to $[H]ash: short_hash date committer $⌗
with the help of git filter⌗
zparseopts -D -K – m:=o_msg # -m mesg is supported [[ $? != 0 ]] && exit 1 o_msg="$o_msg[2]"
for file in “$@”; do dir="$(dirname “$file”)" cd “$dir” 2>/dev/null || continue base="$(basename “$file”)" chmod +w “$base” 2>/dev/null
if ${EDITOR:-/usr/bin/vi} "$base"; then
[[ ! -e "$base" ]] && exit 0 # nothing saved
git add "$base"
if [[ -z "$o_msg" ]]; then
git commit -- "$base"
else
git commit -m "$o_msg" -- "$base"
fi
rm "$base" && git checkout -- "$base"
fi
chmod a-w "$base" 2>/dev/null
cd - >/dev/null
done }CODE
That’s all folks!
And thanks Ton.