Reputation: 407
I want to require SVGs to be committed separately from everything else to keep the diff output of everything else cleaner. For example, I want to disallow commits like this one:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: src/css/main.css
modified: src/images/example.svg
modified: src/index.html
Can this be done with a pre-commit hook? How would that be written?
Edit: I think git ls-files -dmo
will be useful here, but I don't know how to write the script to parse its output.
Upvotes: 3
Views: 240
Reputation: 488453
Can this be done with a pre-commit hook?
Yes. (Note, however, that such hooks can be bypassed.)
How would that be written?
Depends on what language you want to use to write it.
Shell scripts tend to be the simplest since you can just run Git tools directly. Here, you might run git diff-index --name-status
to compare the index (the proposed commit) to the current i.e. HEAD
commit, then read through the files being added, modified, or deleted to see if any have names ending with .svg
, and if any have names ending with anything else. This lets you tweak the rules to allow deleting .svg files while making other changes. Or, if file-status (added/deleted/modified) is not relevant, this is a bit simpler:
# straight from the sample pre-commit hook
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# create a temp file to hold diff output
tmpfile=$(mktemp)
trap "rm -f $tmpfile; exit" 0 1 2 3 15
git diff-index --cached --name-only --diff-filter=ADM $against > $tmpfile
# read the status and names from the temp file.
# we use a temp file simply because "| while read ..." runs
# a sub-shell which means that variable changes don't make
# it back to the parent shell. there are other workarounds
# but this one is simple.
num_svg=0
num_nonsvg=0
while read name; do
case "$name" in
*.svg) num_svg=$((num_svg + 1));;
*) num_nonsvg=$((num_nonsvg + 1));;
esac
done < $tmpfile
# now disallow commit if there are mixed svg and non-svg files
if [ $num_svg -gt 0 -a $num_nonsvg -gt 0 ]; then
echo "this commit affects both .svg files and non-svg files" 1>&2
exit 1
fi
# run any other checks here too
exit 0
(NB: this is entirely untested)
Upvotes: 2