Understanding HEAD in Git

June 07, 2020 ■ 2 min read

Do you know how we can use HEAD in Git to reduce keystrokes when doing git push to remote? But before we talk about it we need to first understand what exactly is HEAD in Git.

Note : If you're using GUI tools(even i use them) to do git push then this tip might not be that helpful. But, i think it is important to just understand the fundamentals concepts like HEAD to know how things work in Git and use it whenever required.

In Git, a Commit is the smallest unit representing our code snapshot at a particular point in Git history.

However, when working with Git apart from commits we keep on using following things:

  • Tags (we won't be talking about this today)
  • Branches
  • HEAD

All these 3 things - Tags, Branches and HEAD are nothing but pointers(references) to our commits(each one in a slightly different way).


To understand it more clearly let's look closely at .git folder of a project containing develop and master branches.

> tree .git

|__ HEAD
|__ refs
    |__ heads
    |   |__ master
    |   |__ develop
    |__ remotes
    |   |__ origin
            |__ develop
            |__ master
    |__ tags
# There are other imp folders too. Removed them here for brevity.


As you can see in the above diagram there are 2 refs of local branches develop and master. If you check their content using cat command like following:

> cat ./git/refs/heads/master

> cat ./git/refs/heads/develop

You can see that they contain which "commit" the "branch" points to.

Checkout to develop branch locally and run following command:

> cat .git/HEAD
ref: refs/heads/develop # HEAD points to "develop" branch

Let's switch to master branch and run above command again:

> cat .git/HEAD
ref: refs/heads/master # HEAD points to "master" branch

As you can see HEAD always(except in some case) points to your currently checked out branch locally. It is a pointer to the currently checked out branch. So, overall these are just references to one another.

HEAD -> Branch -> Commit

Credit to Nina Zakharenko's course on Git In-Depth on FrontendMasters where i learned this concept couple of yrs back.

Git Push

We now know what HEAD is, right? Considering it points to your current branch why not use it to push your current local branch to remote? You must be thinking why even use HEAD i can simply run git push and it works most of the time.

You're right. However, it doesn't works when you try to push some local branch for first time to remote. This is because it doesn't works until upstream branch has been set first.

Every time you run git push for first time on a branch you see the following error:

> git push

fatal: The current branch chore/config-changes has no upstream branch.
To push the current branch and set the remote as upstream, use

git push --set-upstream origin chore/config-changes

And then you go ahead and run command it suggests. This is fine!

Git Push using HEAD

But, now we know what HEAD is! It points to our branch which in turn points to our latest commit on it. So, why not use one of the variant of git push involving HEAD where we don't have to see the same error again. :)


> git push origin HEAD

Yup, that's it 🎉

  • No more errors as git push during the first push.
  • No need to type your branch name as well.
    E.x. - git push origin chore/config-changes

You can even set alias for it in .rc files of your default system shell.

alias gpush="git push origin HEAD"

Then whenever you want to push anything to remote simply run below command without worrying about typing branch names or dealing with errors during first push.

> gpush

That's it. Hope that was useful. I think despite using GUI tools for all such git tasks it is helpful to know small things like this because it can help understand how things work under the hood. So, whenever it is needed you can use them.

As always let me know if there is a better way of doing same thing in comments below. :)

Want to be notified of similar posts? Follow me @punit__d on Twitter 🙂