Suppose you cloned a repository that has a branch named “origin”, and you try to check it out:
$ git checkout origin Note: switching to 'origin'. You are in 'detached HEAD' state.
I’m sorry, what? It should’ve created a local “origin” branch, but it detached the
HEAD instead. Believe me or not, this is the correct behaviour. To explain it, though, we’ll have to learn a bit about Git.
N.B. I’m assuming that you didn’t change Git’s default names for original remote (
origin) and default branch (
master). If you did, everything I say here remains valid, but you’ll have to substitute your preferred names for the default ones.
HEAD, and what it means to detach it
HEAD is Git’s notion of your current position in the repo’s history. Most of the time, it points at a branch, e.g. “master”. When you create a new commit, it’s added to that branch, but
HEAD itself stays still. When you check out a new branch,
HEAD is updated to match.
But you can also check out a tag, or even a random commit. In that case,
HEAD would point at a specific commit. That’s what’s called a “detached HEAD” state: the
HEAD is not attached to any branch. Committing something now would move the
HEAD, but won’t affect any branches. That can be useful for one-off experiments, but can also lead to data loss; please see the “Detached HEAD” section of git-checkout(1).
When you’re cloning a repo, the remote’s
HEAD takes up a new meaning: it’s not just the “current state” of that repo, it’s the default branch. If you ever changed the default on GitHub or GitLab, and then wondered how the clients know about your decision—that’s how.
git remote set-head mentions the following:
Having a default branch for a remote is not required, but allows the name of the remote to be specified in lieu of a specific branch. For example, if the default branch for
originis set to
originmay be specified wherever you would normally specify
That’s literally what happens in our case:
git checkout origin acts like
git checkout origin/master. But
origin/master is a branch, so why do we end up in the “detached HEAD” state?
Remote and local branches
git checkout origin/master result in a detached
origin/master is a remote branch. It’s your local clone’s idea of where
master points to in the remote repository.
A crucial difference between the
origin/master and your local
master is how they are updated:
git rebase, some
git push, some
As a result, it doesn’t make sense for Git to point
HEAD at a remote branch: your local commands like
git commit won’t be able to move the branch anyway. That only leaves one option: detach the
HEAD and point it at the commit referenced by the remote branch.
“But wait”, I hear you cry, “Why does
git checkout feature/123-improve-perf in a fresh clone doesn’t fail, then?” That’s a valid question. The key here is that
feature/123-improve-perf is neither a remote branch nor a local one. There is only a remote branch named
origin/feature/123-improve-perf—note the prefix. Git recognizes this situation and creates a local branch
feature/123-improve-perf that tracks the remote one.
That’s all we need to know right now. For more details, please refer to the relevant chapter of Pro Git.
Putting all of the above together, we finally understand what
git checkout origin does:
origingets resolved into the default branch, i.e.
origin/masteris a remote branch, so checking it out results in a detached
HEADthat points at the commit that’s at the tip of
To achieve what you actually wanted, tell Git to create a branch named “origin” that points at the same commit as
$ git checkout -b origin origin/origin
Drop me a line! (wonder where’s the comments form?)