Does an empty commit have an empty tree in git?

Viewed 619

I read this Git Internals and a few things about tree-object are not very clear.

For intance, the current branch is master. The final commit object on master is an empty commit and is denoted by cmt_end. Given by git-commit-tree, a commit object has only one tree object. Hence, the tree object of cmt_end is denoted by tree_end.

My confusion is:

  • Given by git-commit, git-commit records changes in repository. Does this indicates that tree_end contains the differences between cmt_end and its parent? If so, tree_end should be an empty tree since cmt_end is an empty commit. If not, is it ok to have an empty tree for the empty commit?
  • the --allow-empty option in git-commit, says that an empty commit has the exact same tree as its sole parent commit. Does this indicates that the tree object of a commit records the whole working directory instead of changes when doing git-commit?
2 Answers

A tree object records the whole working directory. A commit object records a tree object and other entries, like the author name, the committer date and the commit message, that you can see in git log -1 <commit> --pretty=raw or git cat-file -p <commit>.

--allow-empty instructs git commit to create a commit object that reuses the tree object of its parent. If the new commit is a root commit that does not have any parent, the tree object is a special one, the empty tree, whose SHA-1 is 4b825dc642cb6eb9a060e54bf8d69288fbee4904. The empty tree maps to an empty directory, without any sub-directories or files in it. The empty in --allow-empty means no changes have been made since the last commit or the initial state.

When an empty commit has a parent, its tree is the same with the parent's. The tree could be the empty tree or a non-empty tree, depending on the tree referenced to by the parent. When the empty commit does not have a parent, its tree is always the empty tree.

As you guessed at the end, the tree object in a commit actually represents the content of the repository at that point, not the changes relative to the previous commit. When a commit is empty, that means that the commit represents no changes relative to the previous commit, but it does not mean the repository contains no files as of that commit. The tree object of an empty commit will be the same as the previous commit's tree object.

Related