Most of the time, HEAD points to a branch name. When you add a new commit, your branch reference is updated to point to it, but HEAD remains the same. When you change branches, HEAD is updated to point to the branch you’ve switched to. All of that means that, in these scenarios, HEAD is synonymous with “the last commit in the current branch.” This is the normal state, in which HEAD is attached to a branch.
As you can see, HEAD points to the controller branch, which points to the last commit. Everything looks perfect. If you running git checkout 87ec91d, This is the detached HEAD state; HEAD is pointing directly to a commit instead of a branch.
As you’ve seen, you detach the HEAD by checking out a commit. That’s already useful by itself since it allows you to go to a previous point in the project’s history. Let’s say you want to check if a given bug already existed last Tuesday. You can use the log command, filtering by date, to start the relevant commit hash. Then you can check out the commit and test the application, either by hand or by running your automated test suite.
Scenario #1: I’m Here by Accident
If you’ve reached the detached HEAD state by accident—that is to say, you didn’t mean to check out a commit—going back is easy. Just check out the branch you were in before:
git checkout <branch-name>
If you’re using Git 2.23.0 or newer, you can also use switch instead of checkout:
git switch <branch-name>
Scenario #2: I’ve Made Experimental Changes and I Want to Discard Them
You’ve entered the detached HEAD state and made a few commits. The experiment went nowhere, and you’ll no longer work on it. What do you do? You just do the same as in the previous scenario: go back to your original branch. The changes you made while in the alternate timeline won’t have any impact on your current branch.
Scenario #3: I’ve Made Experimental Changes and I Want to Keep Them
If you want to keep changes made with a detached HEAD, just create a new branch and switch to it. You can create it right after arriving at a detached HEAD or after creating one or more commits. The result is the same. The only restriction is that you should do it before returning to your normal branch.
Let’s do it in our demo repo:
git branch alt-history
git checkout alt-history