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:
* (detached from abc1234)
master
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)
master
Does anyone know what the difference is, why there is a difference, and what it means?
EDIT:
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
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...")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With