Difference between “(no branch)” and “(detached at abc1234)”

Normally when you run something like this inside of a git repository:

git checkout abc1234

You end up in a detached HEAD state. If you run git branch, the output will look something like this:

  • git equivalent to hg mq?
  • Is it possible to do a git-rebase after doing a git-commit
  • Should I add the Rails 4 bin/ directory to git?
  • GIT extensions does not connect to remote but git bash does
  • How to remove a local Git repo from TortoiseGit?
  • git: Why am I ahead of origin/master with X commits after I do 'git push'?
  • * (detached from abc1234)

    This is fine and expected behaviour.

    I’ve been playing around with pygit2 recently, and have come across something I haven’t seen before. Let’s say I do the following:

    repo = pygit2.discover_repository("/path/to/repo")
    repo.head = "abc1234"

    I would expect the repository to be in a detached HEAD state. For all intents and purposes, I believe it is after doing this. However, the output from git branch looks a bit different:

    * (no branch)

    Does anyone know what the difference is, why there is a difference, and what it means?


    Below is the reflog after cloning a repository using pygit2, assigning a commit SHA1 hash to repo.head, then running git checkout master, then running git checkout myhash:

    69df316 HEAD@{0}: checkout: moving from master to 69df3161f315e9b13ba4bd811635c11f67616598
    d6ece61 HEAD@{1}: checkout: moving from 69df3161f315e9b13ba4bd811635c11f67616598 to master
    69df316 HEAD@{2}:
    d6ece61 HEAD@{3}: clone: from file:///path/to/repo

  • Git Push to Amazon S3 for Deploying Assets?
  • Best workflow using node.js npm and git
  • Cannot use git in Android Studio's terminal
  • GIT: Checkout to a specific folder
  • What are the reasons and cases that cause git merge conflicts?
  • Development environment with multiple developers on a single application
  • 3 Solutions collect form web for “Difference between “(no branch)” and “(detached at abc1234)””

    When in a “detached HEAD” state, git will show “(no branch)” or “(detached from abc)” depending on the contents of the reflog entry.

    In your code, you simply overwrite the value without providing any message and thus no message is written to the reflog (as you can see in the HEAD@{2} entry from your reflog). If there were a similar “checkout” message, the detached text would appear.

    pygit2 provides Reference.log_append() to append entries to the log, so you can create such an entry, though currently it would still create the empty one). The solution would be to use the update method once it supports the newer reflog handling which was introduced in libgit2 0.21.

    The reference-setting methods Reference.set_target() and Repository.set_head() provide a place to put your own identity and message for the reflog, which you can use to provide a message equivalent to the one git’s checkout command would create.

    You can try doing the update as you currently are and writing by hand the entry in the reflog (it’s under .git/logs/HEAD and it’s a text file) to mimic what git would write and you should see the “(detached from abc)” message appear.

    Git is indicating in the first example that you have checked out a commit (not a branch) and thus your head is detached.

    In the second example, Git is indicating that you have checked out something invalid. You are not in a detached HEAD state, your HEAD is pointing to an invalid branch, in particular, it’s pointing at a branch with the name of your commit ID.

    You specified a string argument to repo.head, as if it were a branch name . (And pygit dutifully set HEAD to the branch name, which does not exist.) Instead, you need to specify an Oid, to indicate that the head should be detached:

    repo.head = Oid(hex="abc1234...")

    Check if the version of git was the same in both cases.
    The article “Checking the current branch programatically” from Junio C Hamano states:

    in fact, since release 1.8.3, the output when you are not on any branch, has become something like this:

    $ git checkout v1.8.3
    $ git branch
    * (detached from v1.8.3)

    That means the second output “(no branch)” is consistent with using a git pre-1.8.3, or with the fact that pygit2 uses an older version of libgit2, as commented by Jean Hominal

    If this is produced by the same git, then check the content of HEAD: see “user manual”

    The HEAD then refers to the SHA-1 of the commit instead of to a branch, and git branch shows that you are no longer on a branch:

    $ cat .git/HEAD
    $ git branch
    * (detached from v2.6.17)

    However, in the second case, if pygit2 doesn’t set HEAD at all, the wt_status.c would display no branch.

    Git Baby is a git and github fan, let's start git clone.