32

I was on branch1 when I checkout branch2 like this (both branches are existing).

git checkout origin/branch2

then I got a detached head error:

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.

But then I just checkout branch2 (without origin) then it works ok:

git checkout branch2

So what's the difference between git checkout with and without origin/; and why there was the detached HEAD error when using origin/?

artm
  • 17,291
  • 6
  • 38
  • 54
  • Q: What's the difference between `git checkout branch2` and `git checkout origin/branch2` in my scenario? A: [How can I reconcile detached HEAD with master/origin?](http://stackoverflow.com/questions/5772192/how-can-i-reconcile-detached-head-with-master-origin) – paulsm4 Feb 02 '16 at 05:05
  • http://stackoverflow.com/questions/3965676/why-did-my-git-repo-enter-a-detached-head-state – sfletche Feb 02 '16 at 05:07
  • Related: http://stackoverflow.com/questions/26125162/difference-between-origin-branch-name-and-branch-name – jub0bs Feb 02 '16 at 05:24

2 Answers2

28

The "detached HEAD" message is a warning, not an error.

The reason for it is simple enough. Git has two states you can be in with respect to branches:

  • on a branch, or
  • not on a branch.

When you are on a branch and make new commits, the branch automatically advances to include the new commits.

When you are not on a branch and make new commits, the non-branch also advances, but—here's the reason for the warning—if you then switch to some other branch (so that you are on it), git forgets where you were.1 When you are on a branch, the branch name remembers the new commits; when you are not, there is nothing to remember them.

You can't be on a remote-tracking branch

The branch origin/branch2 is a remote-tracking branch: that is, a branch that remembers "where branch2 was on origin the last time we (our git and origin's git) had a conversation about branches". Because the point of this is to track where they were, git won't let you get "on" that branch and make new commits (which would then remember where you are instead of where they were).

Because you can't be on it, checking it out gives you that "detached HEAD" state instead.

But you can be on a normal (local) branch

The branch branch2 is a normal, ordinary, local branch. It is yours to do with as you wish. You can get on it and make new commits.

(Your local branch can also remember the remote-tracking branch, as its so-called upstream. Git's confusing terminology for this is that your local branch is then "tracking" the remote-tracking branch. The word "tracking" appears too many times here, as does the word "branch", all with different meanings.)


1Actually it saves it for a while, in the reflog for HEAD, but this is only good for 30 days by default.

torek
  • 448,244
  • 59
  • 642
  • 775
  • 1
    Thanks - is it sane to say that we should always `git checkout whatever_branch` (without origin), and then `git push origin whatever_branch`. I understand `origin` means `remote tracking`, but I'm not sure if I understand about "the conversation between our git and remote git about where branch2 was on origin the last time.." – artm Feb 02 '16 at 05:42
  • 1
    Comment answer is two parts, the second part first: The name `origin` here is what git calls a *remote*. It's basically a short name under which git can store the url for the other git, and a prefix for your remote-tracking branches for that other git repository. The "conversation" occurs on fetch and push: the other git lists all their branches, and your git saves all that information away as remote-tracking branches. This is also *how they get updated*: your git talks with their git and gets any new commits and updates your remote-tracking branches. – torek Feb 02 '16 at 05:52
  • 1
    As for what you should `git checkout`, that's up to you, but if you want to *add new good (well, we hope :) ) commits*, then yes, give `git checkout` a local branch name. If you don't have a branch `braX` yet but there's an `origin/braX`, your git will create a `braX` for you that is linked to `origin/braX` and hence is suitable for `git push origin`, yes. – torek Feb 02 '16 at 05:53
4

you should use git checkout --track origin/branch2 to create a local branch of branch2, which tracking the remote origin/branch2

gzh
  • 3,507
  • 2
  • 19
  • 23
  • I have to upvote this, as this solve my queer problem: I have two remote reposotories 1)remotes/origin/MyProject, 2)remotes/origin/origin/MyProject. I can checkout MyProject, but could not checkout the 2nd branch with "git chekcout origin/MyProject"... – ulyssis2 Oct 03 '17 at 13:07