Introduction

In our previous article on working with the git version control system, we explained how to use the git checkout command to retrieve previously committed versions of files from the git repository. In this article, we will talk about a situation that arises if you don’t mention a file name while running the git checkout command and simply type ‘git checkout HEAD~n’ where n is the commit to which to want to move the head to.

How does a repository go into a detached HEAD state?
Using the git checkout command we generally check out a branch of the repository to work with the content within that branch. We’ll talk about branches in detail in a separate article.  For the time being, we’ll define branches as movable pointers to commits in the version history of our git repository. When we initialize a git repository we work with a default branch named master. We may create further branches and subsequently work with those branches. Let’s take a look at the state of the files inside the repository we’ve been using four commits before the current committed state.

[sahil@linuxnix my_first_repo]$ git diff HEAD~4
diff --git a/README.md b/README.md
deleted file mode 100644
index ba76a74..0000000
--- a/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This is a readme file for my first git repository
diff --git a/test.txt b/test.txt
index c66d471..e945f40 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,4 @@
This is a test file!
+Added another line to test file
+Adding a third line to test file
+Adding a fourth line to test file

As you may observe from the above output, the at four commits before the current commit the file test.txt had three fewer lines and we had a file named README.md which we deleted and is no longer available in the repository and hence the /dev/null state for the file.

[sahil@linuxnix my_first_repo]$ pwd
/home/sahil/git/my_first_repo
[sahil@linuxnix my_first_repo]$ ls
README1.md test.txt

Now, let us use git checkout to revert to four commits before the current committed state of the repository.

[sahil@linuxnix my_first_repo]$ git checkout HEAD~4
Note: checking out 'HEAD~4'.

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 performing another checkout.

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 a291f69... Added file test.txt and updated .md files

if we execute the ls command in the repository we will observe that the file we deleted README.md is now back.

[sahil@linuxnix my_first_repo]$ ls
README1.md README.md test.txt

So, now the repository is in a detached HEAD state. But what does it mean?
Detached HEAD is the state wherein a particular commit gets checked out instead of a file or a branch. While in this state we are not on a branch right now. We’re browsing a snapshot of our Git files from a specific commit in the commit history.  The problem with a detached HEAD state is that changes made to files in this state do not belong to any branch i.e., not even the master branch. Due to this changes made to files can easily get lost since they are not being recorded in the context of a revision or branch.

Fixing detached HEAD state:
Getting out of a detached HEAD state is fairly straightforward. Simply execute the following command.

[sahil@linuxnix my_first_repo]$ git checkout master
Previous HEAD position was a291f69... Added file test.txt and updated .md files
Switched to branch 'master'
[sahil@linuxnix my_first_repo]$

This brings us back to the master branch thereby getting rid of the detached HEAD state.

Conclusion

In this article, we explained what is the detached HEAD state of a git repository followed by a practical demonstration wherein we caused the detached HEAD state to occur and then recovered from it to a clean state as well. We hope that you found this explanation to be useful and we look forward towards your suggestions and feedback.

The following two tabs change content below.

Sahil Suri

He started his career in IT in 2011 as a system administrator. He has since worked with HP-UX, Solaris and Linux operating systems along with exposure to high availability and virtualization solutions. He has a keen interest in shell, Python and Perl scripting and is learning the ropes on AWS cloud, DevOps tools, and methodologies. He enjoys sharing the knowledge he's gained over the years with the rest of the community.