Detached HEAD
Before everything, let’s have a look at some stuff. Everything in Git is about commits, and many git commands accept commits as a parameter, i.e.
1 |
git checkout <HASH-ID> |
We have to understand how to reference commits.
Hash
The SHA-1 hash of a commit is the most straightforward method to refer to it. In the
1 |
git log |
output, you may get the hash of each of your commits.
You just need to provide the minimum number of characters necessary to uniquely identify the commit when giving it to other Git commands. For instance, you may use the
1 |
git show |
command to examine the aforementioned commit.
Resolving a branch, tag, or other indirect references into the relevant commit hash can be done by using the
1 |
git rev-parse |
command.
Refs
A ref is an indirect way (a user-friendly alias) of referring to a commit. Refs are stored as plain text files in the
1 |
.git/refs |
directory of your git.
HEAD
HEAD is the symbolic name for the currently checked-out commit. If you open the HEAD
file you will see it is pointing to a branch, for instance:
1 |
ref: refs/heads/hotfix |
If you open the
1 |
.git/refs/heads |
directory, you will see a file for each one of your branches:
Creating a new branch is simply a matter of writing a commit hash to a new file, and that’s the reason why Git branches are so lightweight.
The tags
and remotes
directory works the exact same way. So now let’s see what is a detached HEAD
.
If HEAD
file, instead of pointing to a branch, points directly to a commit, your HEAD is detached when your head is pointing into a commit and not into a branch.
Complete Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
mkdir remote repos1 cd remote/ git init --bare cd ../ cd repos1/ git clone ../remote . touch A.txt git add . git commit -m "A.txt added" git push touch B.txt git add . git commit -m "B.txt added" git push touch C.txt git add . git commit -m "C.txt added" git push touch D.txt git add . git commit -m "D.txt added" git push |
Now if you run
1 |
cat .git/HEAD |
it will show you where HEAD is pointing:
1 |
ref: refs/heads/master |
Now if you run git log
and find the HASH of the commit B and checkout that commit:
1 |
git checkout <commit-B-SHA1> |
You are in a ‘detached HEAD’ state. If you run:
1 |
cat .git/HEAD |
It will indicate a commit and not a branch, actually the HASH-ID of the commit-B
How to solve the detached HEAD
You can simply create a temp branch from where you are, switch to master, merge your temp into your master and delete the temp branch.
1 2 3 4 |
git branch temp git checkout master git merge temp git branch -d temp |
Refs: [1]