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:
HEADusually 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,
HEADdetaches 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
HEADincludegit checkout,git switch, andgit reset. These commands change your current branch or roll back changes in your repository, respectively, thereby updating whereHEADpoints.
- 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 ofHEADbefore 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~1will undo the last commit, movingHEADback one commit. - Referencing previous commits: Use
HEAD~1for the parent of the current commit,HEAD~2for 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.