Git HEAD

Greg Foster
Greg Foster
Graphite software engineer


Note

This guide explains this concept in vanilla Git. For Graphite documentation, see our CLI docs.


In Git, HEAD is a reference to the current commit on the currently checked-out branch. It represents the tip of the branch, pointing to the latest commit you're working on. HEAD can be thought of as the "current branch marker" or the "pointer to the active branch."

  1. Pointer to current commit:

    • HEAD usually points to the latest commit in your current branch, allowing Git to know what the current state of your project is and what changes are staged for the next commit.
  2. Detached HEAD state:

    • When you check out an older commit, a tag, or a remote branch, HEAD detaches and directly points to a specific commit instead of a branch. In this state, any new commits you make will be orphaned when you switch back to a branch, unless you create a new branch starting from the detached HEAD.
  3. Moving HEAD:

    • Typical operations that move HEAD include git checkout, git switch, and git reset. These commands change your current branch or roll back changes in your repository, respectively, thereby updating where HEAD points.

When you switch branches with git checkout branchname or git switch branchname, HEAD moves to point to the tip of the branchname. This update changes the files in your working directory to match the snapshot of the latest commit on that branch.

You can see where HEAD is pointing by looking at the .git/HEAD file in your Git repository, or by using commands like git log, which shows the commit history starting from HEAD.

If you check out a commit that isn't the tip of a branch (e.g., git checkout 4a5e6f), you'll be in a detached HEAD state. Here’s how you can handle it:

  • Making changes in a detached HEAD state: You can commit changes in this state, but if you switch back to a branch, those changes will be hard to find unless you create a new branch from the detached HEAD using git branch new-branch-name.

In advanced Git workflows, you might encounter terms like ORIG_HEAD, MERGE_HEAD, and FETCH_HEAD:

  • ORIG_HEAD: Saved state of HEAD before dangerous operations like git reset.
  • MERGE_HEAD: Points to the commit(s) you're merging into your current branch during a git merge.
  • FETCH_HEAD: Points to the tip of the last fetch that was done.
  • Resetting with HEAD: git reset HEAD~1 will undo the last commit, moving HEAD back one commit.
  • Referencing previous commits: Use HEAD~1 for the parent of the current commit, HEAD~2 for two commits back, etc.

Let's go through a practical example to illustrate how the HEAD can be used in Git operations. We'll demonstrate checking out a previous commit, creating a new branch from that point, and reverting changes using the HEAD.

Suppose you're working on a project and realize you need to review a version of your project from two commits ago and possibly start a new branch from there.

First, let's view the log to understand where HEAD is currently pointing and to find the commit we are interested in:

Terminal
git log --oneline
Terminal
a1b2c3d (HEAD -> master, origin/master, origin/HEAD) Add new feature X
e4f5g6h Add documentation for feature X
h7i8j9k Fix bug in feature Y

Here we can see the HEAD is pointing at commit a1b2c3d "Add new feature x".

Let's checkout two commits before the HEAD:

Terminal
git checkout HEAD~2
Terminal
Note: switching to 'h7i8j9k'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at h7i8j9k Fix bug in feature Y

This output tells you that you are now in a "detached HEAD" state, meaning HEAD is no longer attached to a branch but directly points to a commit.

If you decide that this commit is a good base for a new feature, you can create a new branch right from this detached HEAD:

Terminal
git checkout -b new-feature-branch
Terminal
Switched to a new branch 'new-feature-branch'

Now, HEAD points to the new branch new-feature-branch at the same commit where it was in detached HEAD state.

You can now make changes as needed. Let’s assume you've made some changes and are ready to commit them:

Terminal
git add .
git commit -m "Start developing new feature based on old commit"
Terminal
[new-feature-branch a9b8c7d] Start developing new feature based on old commit
1 file changed, 1 insertion(+)

HEAD has now moved to the new commit a9b8c7d on new-feature-branch.

To verify where HEAD is now pointing after your new commit, run:

Terminal
git show-ref HEAD
Terminal
a9b8c7d37bfeca09d9e9be7a48bf610582f8a5b2 refs/heads/new-feature-branch

This confirms that HEAD is now at the new commit on the new-feature-branch.

This example demonstrates using HEAD to navigate the commit history, check out a specific state of the project, branch from an older commit, and continue development from there.

For further reading on the HEAD in Git, refer to the official Git documentation.

Git inspired
Graphite's CLI and VS Code extension make working with Git effortless.
Learn more

Graphite
Git stacked on GitHub

Stacked pull requests are easier to read, easier to write, and easier to manage.
Teams that stack ship better software, faster.

Or install our CLI.
Product Screenshot 1
Product Screenshot 2