In its pre-commit hook git seems to verify that HEAD exists. If it doesn't it defaults to a special hash of an empty tree to compare the index to.
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
The hash it defaults to is a special hash. I read that I could also get it via
git hash-object -t tree < /dev/null
against is later used like this
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --
Why does the hook do that? In what situations am I able to do a commit but HEAD would be invalid?
HEAD always points to the current commit, because:
ref: refs/heads/master), orIf HEAD contains a raw hash value, then HEAD is definitely valid, because it has to point to a real commit. But... what happens in a completely new, empty repository?
You're on branch master, so HEAD reads ref: refs/heads/master. But what is the tip of branch master? What commit ID is stored in master itself?
There are no commits in the repository. Where will you make master point?
Git's solution to this problem is to keep master invalid. That's when git rev-parse --verify HEAD fails: HEAD says master, but master does not exist yet.
Internally, Git refers to this as an "unborn branch", or sometimes "orphan branch". Using git checkout --orphan newbranch puts Git into this same state for the newly created (except that it's not really created yet) branch newbranch. The HEAD reference now contains ref: refs/heads/newbranch but there is still no newbranch yet. So every unborn-branch state is like this, but there is one particular one you see every time you create a new, empty repository.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With