<pedantic>There are also root commits that have zero parents (a repo can have multiple roots). A merge commit differs _only_ in that it has more than one parent; it otherwise carries no additional data compared to any other commit.</pedantic>
The special treatment that you see when you "git show" a merge commit is computed by comparing the merge commit's tree to its parents' trees.
I'd also add a (4) to your list: a branch is a pointer (a "ref" in git jargon) to a commit that is updated to the most recent commit each time you create a new commit.
Oh, and maybe (5): HEAD is usually an indirect pointer to a commit via a ref, but can also point directly to a commit in which case it is a so-called detached HEAD.
You can even have repositories that only have root commits. I have a git hack that stores blog entries in a git repository. Each entry is a root commit with one branch that points to all of the root commits. A fun crazy hack.
This is where I like Darcs. Your hack is actually the default there, because it is "obvious" that a patch representing a new blog entry doesn't depend on anything.
There, reverting any such patch would simply delete your entry without any more question (unless of course you committed another patch on top of it to, say, correct spelling). I assume this is the kind of advantage you get from your hack?
Yup I saw it a each "blog entry" being its own repository with its own history of corrections, updates etc. There was multiple master branches that groups blog entries such as "public" or with other tags. The real fun came because you could publish your git repository and when someone fetched it if they say used http they would only get the public branch and all those commits, but if you fetched using the key "bob" you could get all of the refs that were both public and bob. Those on the public branch would never know that they are missing refs because they have separate roots. And just to make things more fun you could have encrypted messages to boot with private keys.
The special treatment that you see when you "git show" a merge commit is computed by comparing the merge commit's tree to its parents' trees.
I'd also add a (4) to your list: a branch is a pointer (a "ref" in git jargon) to a commit that is updated to the most recent commit each time you create a new commit.
Oh, and maybe (5): HEAD is usually an indirect pointer to a commit via a ref, but can also point directly to a commit in which case it is a so-called detached HEAD.