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.
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.
Latest posts by Sahil Suri (see all)
- Setting up chrooted ssh jails in Linux - October 8, 2019
- How To exclude copying of specific directories in Linux using cp/scp/rsync - October 7, 2019
- Docker container ports explained - September 27, 2019
- Docker Volumes explained - September 25, 2019
- Docker networking commands explained - September 24, 2019