Search code examples
pythongitlibgit2pygit2

Replicating "git checkout <commit> with PyGit2


I am trying to replicate the behaviour of the command "git checkout (commit)" where (commit) is the reference to as specific commit and not a branch name.

When using this command, the 'HEAD' of the repository point to the commit (detached head) and the working directory is in the same state that it was in this commit.

For the moment, I managed to make the HEAD of the repository point to a commit with PyGit2 :

def go(self, repo_name, version):
    repo = pygit2.Repository(bdd[repo_name])
    #commit = repo.revparse_single(version)
    #repo.reset(version, pygit2.GIT_RESET_HARD)
    repo.set_head(pygit2.Oid(hex=version))
    print repo.head_is_detached

My problem is that I can't find how to rollback the working directory like the Git CLI does. I tried using:

  • repo.checkout_head() : It doesn't do anything on the working directory.
  • repo.checkout() : Crash with a GitError: X conflicts prevent checkout

Is there a way to replicate this behaviour without using Repository.reset(ref, pygit2.GIT_RESET_HARD) ?


Solution

  • Low-level checkout is git read-tree -um HEAD $target && git update-ref HEAD $target; pygit2 apparently understands only the one-tree read and none of the options on that, so however it's doing checkout and merge and any number of other operations it doesn't offer more than a crude mock-up of actual git. It looks like you could kludge it with add a ref to your commit, check that out, then reset HEAD and delete the ref.