Last modified: June 11, 2024

This article is written in: 🇺🇸

Understanding HEAD

HEAD is a special pointer in Git, which refers to the currently checked-out snapshot of your project. This could be a particular commit, a branch, or a tag. It serves as a kind of "you are here" marker, indicating what part of the project history you're currently looking at or working with. When you make a commit, HEAD updates to point to the latest commit.

HEAD can exist in two forms: attached and detached.

The Concept of a Detached HEAD

A "detached HEAD" occurs when HEAD points to a specific commit, and not the latest commit of a branch. This could happen when you checkout a specific commit or tag, or when you switch to a remote branch. In a detached HEAD state, any new commits you create won't belong to any branch. To preserve your work, you'd need to create a new branch or merge these changes into an existing branch.

For instance, consider a repository with the following commit history:

A <-- B <-- C <-- D <-- E (master, HEAD)

Here, both the master branch and the HEAD pointer refer to the most recent commit (E). So, the HEAD is not detached.

However, if we switch to commit C, the HEAD pointer detaches and points to C, but the master branch remains at E:

A <-- B <-- C (HEAD) <-- D <-- E (master)

In this state, any new commits won't be part of the master branch. Let's say we make a new commit (F), this commit will be unassociated with any branch:

A <-- B <-- C (HEAD) <-- F
             \
              D <-- E (master)

To keep commit F in the repository's history, we need to create a new branch from HEAD or merge F into an existing branch.

Detaching HEAD: Switching to a Specific Commit

In Git, you can switch to a specific commit and enter a detached HEAD state by using the git switch command followed by the hash of the commit you want to check out. This hash is a unique identifier for each commit. For example:

git switch b4d373k8990g2b5de30a37bn843b2f51fks2b40

Alternatively, you can use the git checkout command to achieve the same result. The checkout command is older and has more options, but switch was introduced to make certain actions more intuitive:

git checkout b4d373k8990g2b5de30a37bn843b2f51fks2b40

Both commands detach your HEAD pointer and place it on the specified commit.

Creating a Branch from a Detached HEAD

While working in a detached HEAD state, you might make some changes and commit them. These changes are not associated with any branch. To prevent these changes from being lost when you switch branches, you can create a new branch at the current commit.

Use the git branch command followed by your chosen branch name. For example, to create a new branch called new_branch:

git branch new_branch

This creates a new branch named new_branch from the current commit. To switch to this newly created branch and exit the detached HEAD state, use the git switch or git checkout command:

git switch new_branch

Now, new_branch contains all the commits you made while HEAD was detached, ensuring your changes are preserved.

Preventing a Detached HEAD State

To prevent ending up in a detached HEAD state, it's recommended to avoid explicitly checking out specific commits or tags. Instead, you should primarily interact with different versions of your codebase using branches.

For instance, if you wish to work with an older version of your code, instead of directly checking out that specific commit, create a new branch from that commit and switch to the new branch. This approach allows you to work on the older version of your code without disturbing the main codebase.

Here's an example of how to create a new branch named old_version from a specific commit and switch to it:

git branch old_version b4d373k8990g2b5de30a37bn843b2f51fks2b40
git switch old_version

Switching Back to a Branch from a Detached HEAD

If you find yourself in a detached HEAD state and wish to switch back to a branch (let's say the master branch), use the git switch or git checkout command followed by the branch name:

git switch master

With this command, you will switch back to the master branch. Any new commits you make will now be added to the history of the master branch.

Merging Changes from a Detached HEAD into a Branch

If you've made some changes in a detached HEAD state and want to merge these changes into a branch (e.g., master), you can do so using the git merge command followed by the commit hash or tag name:

git checkout master
git merge b4d373k8990g2b5de30a37bn843b2f51fks2b40

This command creates a new commit on the master branch, combining the changes from the detached HEAD with those in the master branch. If there are conflicts between the two sets of changes, Git will prompt you to resolve them before the merge can be completed.

Table of Contents

  1. Understanding HEAD
  2. The Concept of a Detached HEAD
  3. Detaching HEAD: Switching to a Specific Commit
  4. Creating a Branch from a Detached HEAD
  5. Preventing a Detached HEAD State
  6. Switching Back to a Branch from a Detached HEAD
  7. Merging Changes from a Detached HEAD into a Branch