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.
Here the head is attached to the master branch. The master branch has commits A, B, and C.
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.txt
which 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