Search code examples
gitgithubmergebitbucketgit-detached-head

Why is it always a detached HEAD?


I have a git repo with two remote.

    origin/master        cm/master
         |                  |
         |                  |
       sfcc--------------cm/sfcc-18
         |
         |
       feature

The above is the basic structure of my repo. Branch sfcc is pulled from another branch sfcc from cm.

Both the branches sfcc and feature are also pushed to the remote origin.

Branch sfcc is not yet merged to the origin/master.

Now I am on the local branch feature. I have not yet done any changes other than creating these branches. I try to switch to origin/sfcc which puts me in a detached state.

HEAD is now at 9d4f1707 Merge branch 'sfcc-18' of https://github.com/bla-bla-cm into sfcc.

Again when I try to checkout origin/migration I get the same message.

On git status i get working tree clean and nothing to commit.

Why do I get into this situation even when nothing was changed?

In case something has changed on cm/sfcc-18, I do not want it to be tracked with respect to the cm repo changes. I have set the upstream tracking for origin/sfcc with origin/master.

I cannot checkout origin/master as well. I get the following message

Previous HEAD position was 9d4f1707 Merge branch 'sfcc-18' of https://github.com/bla-bla-cm into sfcc

HEAD is now at e71242f0 .gitignore created online with Bitbucket


Solution

  • The most likely reason you are seeing your checkouts result in detached head is that you are referencing the branch you want to check out as origin/<branch-name> instead of simply <branch-name>.

    While technically both will result in HEAD being at the same commit, the way Git behaves in the two cases is different.

    git checkout origin/<branch> checks out a specific commit as a detached head, even if you have a local branch with the same name, as if you had used --detach

    git checkout <branch> will check out a local branch, if it exists. If it doesn't, and a single remote tracked branch does exist with that name, it will create a local branch with that name and set it to track the remote branch. See git checkout for more information.

    In your case, you should be able to just type git checkout sfcc-18, and a new local branch will be checked out that will track cm/sfcc-18.

    Note however if you wanted to checkout origin's master as a new local branch, you would need git checkout -b master --track origin/master