What is Git HEAD?

A deep dive into Git's ubiquitous HEAD reference object.

Seann Hicks

Seann Hicks

Monday, July 5, 2021

What is Git HEAD?

The Git HEAD is a Git reference object that represents the current branch. Checking out a branch will change the HEAD to point to the checked out branch. The HEAD will point to the tip of a branch by default, but can be set to point to any commit. When pointed at a specific commit the HEAD is considered to be in a ‘detached’ state. Detaching is useful if you need to branch from a midpoint commit instead of the branch HEAD.

Git reference objects

The Git reference objects include tags, branches and remote references. The Git HEAD is a special reference object that always points to the current branch. To list all reference objects in a local repository use the “git show-ref” command:

$ git show-ref

git show-ref command output

In this example you can see the references in the repository include the master branch, the remote master branch and the Add-Email-Collection branch.

To display refs including the HEAD:

$ git show-ref --head

git show-ref --head command output

Add the --head argument displays the commit that HEAD is currently referencing. Since the current branch is ‘Add-Email-Collection’ the HEAD is currently set to this branch.

Detached HEAD Branches

When you checkout a commit by name, git creates an anonymous branch called a detached HEAD.

According to “Version Control with Git, O'reilly, 2012”

“Git creates a detached HEAD when you:

Let’s do the ‘Check out a commit that is not the head of a branch’ scenario. The other scenarios require a deeper dive, so I will leave those for another post.

Continuing the example from above, running the command:

$ git checkout d89fb8e72bf82fd

detaches HEAD from the “Add-Email-Collection” branch and points it directly at the “d89fb8e…” commit.

git checkout against a commit command output

So instead of HEAD pointing to the “Add-Email-Collection” branch, and the branch pointing to the “d89fb8e” commit.  The Git HEAD is now pointing directly at the commit, and is thus detached from a branch.

Running the "git status" or "git branch" commands indicate that the HEAD is in a detached state.

git detached head output

So, if I commit the current working directory changes they will be checked into the anonymous branch. Git will readily create a commit for the changes.

git checkout with orphaned change output

Committing Changes on a Detached HEAD

You can see here that I have commited the pending changes against the detached HEAD and changed branches back to the HEAD. Git warns that my change is floating around unattached to a branch, and thus is not part of a change stream. At this point Git recommends creating a branch from the commit with:

$ git branch <new-branch-name> 6a44441

I also have the option to cherry pick the commit into my current branch, or just leave it to twist in the ether, but I don’t want to lose track of this change so I will merge it in.

Git reflog

The “git reflog” command displays the history of HEAD references and provides useful information to make sense of how the HEAD evolved and where commits may have been orphaned.

git reflog command output

Let’s pick through this output.

As you can see, “git reflog” is a useful forensic tool for telling the story of the HEAD reference object.

Fixing an orphaned commit

Using a Branch

I’m going to proceed with git’s suggestion to branch from the orphaned commit. This action is the equivalent to branching from the ‘Add-Email-Collection’ branch and committing to the branch directly.

git branch orphaned-changes 6a44441

So now if I run git show-ref

git show-ref with orphaned changes

You can see that the “orphaned-changes” branch points to the commit created on the anonymous branch. I can now switch to this branch and work from it, or merge it into my ‘Add-Email-Collection’ branch.

Using a Cherry-pick

For the cherry-pick example I’ve detached the HEAD again, made a change and committed on an anonymous branch. Below are the console commands and output from git reflog showing the history.

git cherry-pick command output

I create a commit 4f6ef34… and checkout the feature branch. Instead of branching and merging I can quickly resolve the change into the current branch with a cherry-pick. This saves having to create, merge and delete a branch.

Summary

The git HEAD is a convenience reference object that specifies the current branch context. It tracks against the current checkout and if that checkout is not a branch head, then the HEAD is considered detached. It allows you to easily reference any commit in the change history and branch changes from that commit.

Related Articles

Some related articles:

Sources Cited

Photo by Sven Gauditz on Unsplash

Sign-up to receive the weekly post in your inbox. I don't share email addresses, unsubscribe at any time.

Email Address