Git Under the Hood, Part 2: Referencing Commits
**This article is inspired by [1]***

There are two approaches to reference commits in a Git tree: (i) absolute referencing, and (ii) relative referencing. With absolute referencing, different commits can be referenced via their unique identifiers (SHA-1 code, branch, or tag name). The other way of referring to commits is by relative referencing, which is defined relative to a baseline or starting point. The baseline could be any commit and is specified by a SHA-1 identifier, branch/tag name, or HEAD pointer. Multiple ways of working with both referencing approaches are shown in Figure 1.

Among the relative referencing approaches, the “caret parent (^) and Tilda spec (~)” are the most widely used. These two symbols ^ and ~ enable movement within the Git tree. Placing the ~ symbol after HEAD means “move one step backward in the tree”. For example, HEAD~ refers to the parent commit of HEAD and HEAD~~ refers to the grandparent commit of HEAD. We can also specify a number (n) after the ~ to move to the nth ancestor of the commit (e.g., HEAD~1 is equivalent to HEAD~ or HEAD~2 is equivalent to HEAD~~). However, this can be problematic when there are multiple branches in the Git tree. For instance, when a commit is the result of merging multiple branches¹[2], how can we refer to each parent commit? To answer this, we first need to further refine the definition of ~. Although we can say that ~ refers to the parent commit, the more precise definition would be that it refers to the first parent commit. The first parent is on the branch you were on when you ran git merge, while the second parent is on the branch that was merged in, thus ~ always refers to the commit of the first parent. In order to visit other parents, we use the ^ symbol. If a commit has five parents (for example, five branches were merged), HEAD^ refers to the first parent, HEAD^^ refers to the second parent and so on and so forth. Similar to ~, instead of repeating the ^ symbol five times, we could use HEAD ^ 5.
These two symbols can also be combined to explore every possible commit in the Git tree. Figure 2 illustrates ways of using the combination of those two symbols in several examples. Please note that in this diagram only some of the possible combinations are demonstrated.

Previously, HEAD was introduced as a pointer to the most recent commit. Although most of the time HEAD does that, sometimes we want to move the HEAD pointer to earlier commits using git checkout <commit_reference>
to make changes or check information. This would lead to the detached HEAD state, meaning HEAD is not pointing to the most recent commit but some earlier commit. To exit the detached HEAD state, we use the git checkout master
command.

Footnotes
- git merge can merge more than one commit (i.e., two or more) into the current branch