git detached HEAD Explained [Easy Examples]


GIT

 

Introduction to git detached head

Git detached head is a state whereby the head points to a commit and not the branch using the git checkout command.  It’s a normal occurrence while working in git especially when you want to make a change or try something new with an old commit. It's important that you follow the right procedure to get back to a branch or git repo after working in the detached head state. Failure to do so you may end up forgetting some of the commits and even losing them.

In this tutorial about git detached head, we will learn how to get into the detached head state and reconnect to the master branch or a new branch.

 

Git detached head workflow

The diagram below illustrates how a detached head state in git occurs.

git detached HEAD Explained [Easy Examples]
Without git detached HEAD

Here the head is attached to the master branch. The master branch has commits A, B, and C.

git detached HEAD Explained [Easy Examples]
With git detached HEAD
The above diagram illustrates a detached head state after applying the git checkout <commit> command.

 

Setting up the lab environment

To practice how git detached head works, you will need to set up a lab environment for running the experiments. I will, therefore, step up my local workstation windows 10 pro and use git version 2.32.0.windows.2. Next, we will clone a remote repository detached-head and start the practice as shown below:

$ git clone https://github.com/Josephine-Techie/detached-head.git
Cloning into 'detached-head'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

 

How to work with git detached head

You can get into a detached head state in two ways:

  • Running the git checkout --detach function in an active repository
  • Applying the git checkout <commit> command to an old commit

 

Example-1: How to get into a detached head state in git

To switch to a detached head in git you will run the git checkout <commit > function which we will illustrate in the example below.

First, we shall commit several changes in the master branch in the local project detached-head.

$ touch testfile.txt

$ git commit -m "testfile.txt"
[master 0c0294d] testfile.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 testfile.txt

$ echo "testfile edited.txt">>testfile.txt

$ git commit -m "testfile edited.txt"
[master 13f6517] testfile edited.txt
 1 file changed, 1 insertion(+)
$ echo "testfile edited first line.text">>testfile.txt

$ git commit -m "testfile edited first line.txt"
[master 5b04567] testfile edited first line.txt
 1 file changed, 1 insertion(+)

Next, we shall run the git log --oneline command to view all the commits as follows;

$ git log --oneline
5b04567 (HEAD -> master) testfile edited first line.txt
13f6517 testfile edited.txt
0c0294d testfile.txt
8051a68 (origin/master, origin/HEAD) Initial commit

To create a detached head in git we shall run git checkout commit 0c0294d a second commit among the displayed.

$ git checkout 0c0294d
Note: switching to '0c0294d'.

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 switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 0c0294d testfile.txt

Notice the alert that you are now in a detached head state. Alternatively, you can use the git checkout HEAD~2 function and get the same results.

 

Example-2: How to reattach the head to a new branch

To reattach the head back we will require to create a new branch as recommended in the git alert.

To build on the above example, we shall create a new branch test-branch in the local repository detached-head. We will then switch to it to retain the detached commit 0c0294d. To do that we shall run the git switch –c <new-branch> or alternatively git checkout –b <new-branch> command.

$ git switch -c test-branch
Switched to a new branch 'test-branch'

Next, we shall push the commit to update the new branch status.

$ git push --set-upstream origin test-branch
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 283 bytes | 283.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'test-branch' on GitHub by visiting:
remote:      https://github.com/Josephine-Techie/detached-head/pull/new/test-branch
remote:
To https://github.com/Josephine-Techie/detached-head.git
 * [new branch]      test-branch -> test-branch
Branch 'test-branch' set up to track remote branch 'test-branch' from 'origin'.

Lastly, we shall run git log --oneline command to view the reattached head to the new branch test-branch.

$ git log --oneline
0c0294d (HEAD -> test-branch, origin/test-branch) testfile.txt
8051a68 (origin/master, origin/HEAD) Initial commit

 

Example-3: How to reattach the head to the master after a detached head

Understand that being in a detached head state doesn’t affect your work on either the active branch before detaching or other branches.

Git recommended procedure of reattaching the head is to create a new branch first. In this case, since we want to commit to the same branch after detaching the head we will need to use git merge afterwards.

Let’s demonstrate how this works using the example below:

First, we shall check out to master branch .

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)

Next, we will run the git log --oneline command to be able to select the commit to detach and make changes.

$ git log --oneline
62e5449 (HEAD -> master) testfile-2 edited.txt
37059d1 testfile-2.txt
fd15382 (origin/master, origin/HEAD) Initial commit

Now let’s detach commit 37059d1 and commit changes to it as follows using the git checkout <commit> command.

$ git checkout 37059d1
Note: switching to '37059d1'.

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 switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

You can turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 37059d1 testfile-2 edited.txt

Here we shall commit changes to the file:

$ echo "testfile-2 edited.txt">>testfile-2.txt

$ git commit -m "testfile-2 edited.txt"
[13f6517] testfile-2 edited.txt
 1 file changed, 1 insertion(+)

Next, we shall check out a new branch mybranch to save the commit 37059d1 testfile-2 edited.txtwhich we shall later merge into the master branch

$ git checkout -b mybranch
Switched to a new branch 'mybranch'

To merge into master we shall checkout master first:

$ git checkout -b master
Switched to a master branch

$ git merge mybranch
Merge branch 'mybranch'

Next, we will run git status to ascertain the merge.

$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:
        new file:   tesfile-2

Here we will have to commit the new changes to complete the merge as alerted by git in the above output.

$ git commit -m "new file:   tesfile-2"
[master 9c8558f] new file:   tesfile-2

Lastly, we will run git log  - -oneline to view the edited commit now in the master branch and not mybranch after the merge.

$ git log --oneline
9c8558f (HEAD -> master) new file:   testfile-2
e4110f9 (mybranch) testfile-2 edited firstline.txt
62e5449 testfile-2 edite.txt
37059d1 testfile-2.txt
fd15382 (origin/master, origin/HEAD) Initial commit

The head is now reattached back to the master branch with the new changes new file:   testfile-2.

 

Summary

We have covered the following topics in this tutorial about git detach head:

  • How does git detach head work
  • How to reattach the head to a new branch
  • How to reattach the head to the master after a detached head

 

Further Reading

Git-detach-head

 

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment