What is HEAD in Git?

Viewed 635067

You see the Git documentation saying things like

The branch must be fully merged in HEAD.

But what is Git HEAD exactly?

25 Answers

You can think of the HEAD as the "current branch". When you switch branches with git checkout, the HEAD revision changes to point to the tip of the new branch.

You can see what HEAD points to by doing:

cat .git/HEAD

In my case, the output is:

$ cat .git/HEAD
ref: refs/heads/master

It is possible for HEAD to refer to a specific revision that is not associated with a branch name. This situation is called a detached HEAD.

There is a, perhaps subtle, but important misconception in a number these answers. I thought I'd add my answer to clear it up.

What is HEAD?

HEAD is YOU

HEADis a symbolic reference pointing to wherever you are in your commit history. It follows you wherever you go, whatever you do, like a shadow. If you make a commit, HEAD will move. If you checkout something, HEAD will move. Whatever you do, if you have moved somewhere new in your commit history, HEAD has moved along with you. To address one common misconception: you cannot detach yourself from HEAD. That is not what a detached HEAD state is. If you ever find yourself thinking: "oh no, i'm in detached HEAD state! I've lost my HEAD!" Remember, it's your HEAD. HEAD is you. You haven't detached from the HEAD, you and your HEAD have detached from something else.

What can HEAD attach to?

HEAD can point to a commit, yes, but typically it does not. Let me say that again. Typically HEAD does not point to a commit. It points to a branch reference. It is attached to that branch, and when you do certain things (e.g., commit or reset), the attached branch will move along with HEAD. You can see what it is pointing to by looking under the hood.

cat .git/HEAD

Normally you'll get something like this:

ref: refs/heads/master

Sometimes you'll get something like this:

a3c485d9688e3c6bc14b06ca1529f0e78edd3f86

That's what happens when HEAD points directly to a commit. This is called a detached HEAD, because HEAD is pointing to something other than a branch reference. If you make a commit in this state, master, no longer being attached to HEAD, will no longer move along with you. It does not matter where that commit is. You could be on the same commit as your master branch, but if HEAD is pointing to the commit rather than the branch, it is detached and a new commit will not be associated with a branch reference.

You can look at this graphically if you try the following exercise. From a git repository, run this. You'll get something slightly different, but they key bits will be there. When it is time to checkout the commit directly, just use whatever abbreviated hash you get from the first output (here it is a3c485d).

git checkout master
git log --pretty=format:"%h:  %d" -1
# a3c485d:   (HEAD -> master)

git checkout a3c485d -q # (-q is for dramatic effect)
git log --pretty=format:"%h:  %d" -1   
# a3c485d:   (HEAD, master)

OK, so there is a small difference in the output here. Checking out the commit directly (instead of the branch) gives us a comma instead of an arrow. What do you think, are we in a detached HEAD state? HEAD is still referring to a specific revision that is associated with a branch name. We're still on the master branch, aren't we?

Now try:

git status
# HEAD detached at a3c485d

Nope. We're in 'detached HEAD' state.

You can see the same representation of (HEAD -> branch) vs. (HEAD, branch) with git log -1.

In conclusion

HEAD is you. It points to whatever you checked out, wherever you are. Typically that is not a commit, it is a branch. If HEAD does point to a commit (or tag), even if it's the same commit (or tag) that a branch also points to, you (and HEAD) have been detached from that branch. Since you don't have a branch attached to you, the branch won't follow along with you as you make new commits. HEAD, however, will.

What is HEAD in Git? (conceptually)

HEAD is a pointer to the currently checked out branch or commit, it answers the question: Where am I right now in the repository? Or, in other words, it's Git's way of knowing on which commit to mirror your local Working Tree on, and whether you're currently working on a branch (attached) or not (detached).

Detached HEAD

HEAD can be in either of two states, attached or detached, depending on if you've checked out a branch or not. Default state is attached, where any manipulation to the history is automatically recorded to the branch HEAD is currently referencing.

In detached state experimental changes can be made without impacting any existing branch. See infographic below illustrating the difference between committing in attached vs detached state.

Illustration of HEAD in attached and detached state.

A common misconception is that the message You are in 'detached HEAD' state is of erroneous tone, when in fact it just describes how HEAD is referencing the current snapshot.

Operations than can leave HEAD in detached state:

  • Checking out a particular commit, i.e.
    $ git checkout 14ko3
    
  • Explicitly checking out a remote branch, i.e.
    $ git checkout origin/master
    
  • Switching to a branch using the detached flag, i.e.
    $ git switch master --detached
    
  • Checking out a tag, i.e.
    $ git checkout v1.0.1
    
  • Performing an interactive rebase, or a regular rebase containing conflicting changes

Moving from detached to attached state

To move from detached to attached state, you can either create a new branch from where you're at, or switch back to an existing branch.

Note: any commits created in detached state will eventually (post garbage collection) be discarded if you switch to another existing branch, without first persisting your changes in a new branch.

Inspecting the state of HEAD

Figuring out which state HEAD is currently in can be done in different ways, here are two options.

  • Using show
    $ git show HEAD --oneline
    14ko3 (HEAD, master) C1
    
    # If attached, the output would have been
    14ko3 (HEAD -> master) C1
    
  • Using status
    $ git status
    HEAD detached at 14ko3
    

What is HEAD exactly? (technically)

If you ever want to explicitly see what HEAD is referencing you can always inspect the .git/HEAD file, which is the actual file Git uses internally to manage HEAD. The file contains the name of the branch or commit hash depending on if HEAD is detached or not.

$ cat .git/HEAD
ref: refs/heads/master

# If detached, the output would have been
14ko36e295f1a98ec57397b3acc7bc247da61ff5

Source: Above excerpt is taken from this full length post on the subject: What is HEAD in Git?

It feels like that HEAD is just a tag for the last commit that you checked out.

This can be the tip of a specific branch (such as "master") or some in-between commit of a branch ("detached head")

In addition to all definitions, the thing that stuck in my mind was, when you make a commit, GIT creates a commit object within the repository. Commit objects should have a parent ( or multiple parents if it is a merge commit). Now, how does git know the parent of the current commit? So HEAD is a pointer to the (reference of the) last commit which will become the parent of the current commit.

Git is all about commits.
And Head points to the commit which you currently checked out.

$ git cat-file -t HEAD
commit

Whenever you checkout a branch, the HEAD points to the latest commit on that branch. Contents of HEAD can checked as below (for master branch):

$ cat .git/refs/heads/master
  b089141cc8a7d89d606b2f7c15bfdc48640a8e25

I am also still figuring out the internals of git, and have figured out this so far:

Let's say the current branch is master.

  1. HEAD is a file in your .git/ directory that normally looks something like this:
% cat .git/HEAD
ref: refs/heads/master
  1. refs/heads/master is itself a file that normally has the hash value of the latest commit of master:
% cat .git/refs/heads/master 
f342e66eb1158247a98d74152a1b91543ece31b4
  1. If you do a git log, you will see that this is the latest commit for master:
% git log --oneline 
f342e66 (HEAD -> master,...) latest commit
fa99692 parent of latest commit

So my thinking is the HEAD file is a convenient way to track the latest commit, instead of remembering long hash values.

HEAD is nearly literally the head of the branch. So when you are observing a branch, you are looking at the latest commit, which is this same head of the branch. However, you can point yourself to be looking at another commit further back in the history of this branch, and when you do that, you are moving the HEAD to a previous commit. As the HEAD belonged naturally to the latest commit in the branch, it is considered detached.

A visual representation. Each branch is a caterpillar, and each commit is a segment of the creature. So the HEAD will be in the segment that is most ahead. If you remove the HEAD from that to another segment to be used, you have detached the head from the natural segment. Hope it makes any sense.

Now if you detach the HEAD in the main branch, then checkout newFeature, and checkout main again, the HEAD will still be detached, and on top of another commit. I see the HEAD as a looking glass that you can point at where you want.

A branch is actually a pointer that holds a commit ID such as 17a5. HEAD is a pointer to a branch the user is currently working on.

HEAD has a reference filw which looks like this:

ref:

You can check these files by accessing .git/HEAD .git/refs that are in the repository you are working in.

HEAD actually is just a file for storing current branch info

and if you use HEAD in your git commands you are pointing to your current branch

you can see the data of this file by cat .git/HEAD

There can be multiple heads in a repository. And total number of heads is always equals to total number of branches present in the repository,which means heads are nothing but latest commits of each branch

But there will be only one HEAD for a repository.HEAD is a reference which references the latest commit done at the current branch.

Its like eye of git user.Whichever commit the HEAD is referencing to, the repository starts reflecting the condition the repository had during that particular commit.

The basic nature of HEAD is to always refer the latest commit of current branch but we can move HEAD to any commit of the current branch by using git checkout "commit-hash"

Note: We can easily get commit-hash by using command git log --oneline

As a concept, the head is the latest revision in a branch. If you have more than one head per named branch you probably created it when doing local commits without merging, effectively creating an unnamed branch.

To have a "clean" repository, you should have one head per named branch and always merge to a named branch after you worked locally.

This is also true for Mercurial.

Related