Understanding HEAD in Git
In this post, we will learn about
HEAD in Git & how we can use it to reduce keystrokes when doing
git push to remote.
Note: If you're using GUI tools to do a git push, this tip might not be that helpful. However, IMO it is essential to understand the fundamentals concepts like
HEADto 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. We all are aware of commits in Git. However, besides commits in Git, there are three other useful things.
- Tags (we won't be talking about this today)
All these three things -
HEAD are nothing but pointers to our commits.
To understand it more clearly, let's look closely at the
.git folder of a project containing develop and master branches.
> tree .git .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 two refs of local branches,
> cat ./git/refs/heads/master 12de9b3658d9b4424efe03c3ac3281facf288c13 > cat ./git/refs/heads/develop dlk0erflke13658d9b4424ef2o2p3po3281fa232
If you check their content using the
cat command like the above, you will see that they contain which "commit" the "branch" points to.
Let's check what
HEAD contains. Checkout to
develop branch locally and run the following command:
> cat .git/HEAD ref: refs/heads/develop # HEAD points to "develop" branch
master branch and running the above command again:
> cat .git/HEAD ref: refs/heads/master # HEAD points to "master" branch
As you can see,
HEAD always points to your currently checked-out branch locally. It is a pointer to the now checked-out branch. In other words, 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 using HEAD
We now know what HEAD is! 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 run
git push, and it works most of the time.
You're right. However, it doesn't work when you try to push some local branch to remote for the first time. That is because it only works after the upstream branch has been set.
Every time you run
git push for the first time on any new 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! 😅
As per our recent learning,
HEAD points to our currently checked-out branch. 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 pushduring the first push.
- No need to type your branch name as well.
E.x. - git push origin chore/config-changes
To reduce keystrokes even further, you can set an alias in the
.rc files of your default system shell.
alias gpush="git push origin HEAD"
Now, you can run the below command whenever you want to push anything to the remote without worrying about typing long branch names or dealing with errors during the first push.
Despite using GUI tools for all such git tasks, knowing small things like this is helpful because it can help understand how things work under the hood. So, whenever needed, we can use them. I hope that was useful. Thanks for reading 🙂