What is HEAD in Git?
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."
How does HEAD work?
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.
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.
- When you check out an older commit, a tag, or a remote branch,
Moving HEAD:
- Typical operations that move
HEAD
includegit checkout
,git switch
, andgit reset
. These commands change your current branch or roll back changes in your repository, respectively, thereby updating whereHEAD
points.
- Typical operations that move
Working with HEAD
Checking out branches
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.
Investigating history
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
.
Detached 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
.
Advanced uses of HEAD
Multiple HEADs in Git Workflows
In advanced Git workflows, you might encounter terms like ORIG_HEAD
, MERGE_HEAD
, and FETCH_HEAD
:
ORIG_HEAD
: Saved state ofHEAD
before dangerous operations likegit reset
.MERGE_HEAD
: Points to the commit(s) you're merging into your current branch during agit merge
.FETCH_HEAD
: Points to the tip of the last fetch that was done.
Using HEAD
in various Git operations
- Resetting with HEAD:
git reset HEAD~1
will undo the last commit, movingHEAD
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
.
Practical example
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.
Step 1: Viewing the log to find the commit
First, let's view the log to understand where HEAD
is currently pointing and to find the commit we are interested in:
git log --oneline
a1b2c3d (HEAD -> master, origin/master, origin/HEAD) Add new feature Xe4f5g6h Add documentation for feature Xh7i8j9k Fix bug in feature Y
Here we can see the HEAD is pointing at commit a1b2c3d "Add new feature x".
Step 2: Checking out a previous commit
Let's checkout two commits before the HEAD
:
git checkout HEAD~2
Note: switching to 'h7i8j9k'.You are in 'detached HEAD' state. You can look around, make experimentalchanges and commit them, and you can discard any commits you make in thisstate without impacting any branches by switching back to a branch.If you want to create a new branch to retain commits you create, you maydo 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.
Step 3: Creating a new branch from detached head
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:
git checkout -b new-feature-branch
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.
Step 4: Making changes and committing
You can now make changes as needed. Let’s assume you've made some changes and are ready to commit them:
git add .git commit -m "Start developing new feature based on old commit"
Console output
[new-feature-branch a9b8c7d] Start developing new feature based on old commit1 file changed, 1 insertion(+)
HEAD
has now moved to the new commit a9b8c7d
on new-feature-branch
.
Step 5: Checking the current status of head
To verify where HEAD
is now pointing after your new commit, run:
git show-ref HEAD
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.