thomascirca
thomascirca

Reputation: 933

Checking out a branch with GitPython. making commits, and then switching back to the previous branch

I'm using the GitPython library to do some simple Git manipulation and I'd like to checkout a branch, make a commit, and then checkout the previous branch. The docs are a little confusing on how to do this. So far, I have this:

import git
repo = git.Repo()
previous_branch = repo.active_branch
new_branch_name = "foo"
new_branch = repo.create_head(new_branch_name)
new_branch.checkout()
repo.index.commit("my commit message")  # this seems wrong
## ?????

I can tell that this works by verifying it via git commands, but I get the feeling that I'm doing this incorrectly. I'm not how to switch back to the previous branch safely sort of using the raw git commands (from within the library directly).

Upvotes: 10

Views: 19699

Answers (2)

sezanzeb
sezanzeb

Reputation: 1139

While the above answer is correct, I found the info from the docs a bit overwhelming. If you just want to switch to an existing branch, you can do:

repo.head.reference = repo.heads["main"]

mypy logged an error for this though. In that case you can also use

repo.head.set_reference(repo.heads["main"])

Upvotes: 0

David Neiss
David Neiss

Reputation: 8237

From http://gitpython.readthedocs.io/en/stable/tutorial.html

Switching Branches

To switch between branches similar to git checkout, you effectively need to point your HEAD symbolic reference to the new branch and reset your index and working copy to match. A simple manual way to do it is the following one

    # Reset our working tree 10 commits into the past
    past_branch = repo.create_head('past_branch', 'HEAD~10')
    repo.head.reference = past_branch
    assert not repo.head.is_detached
    # reset the index and working tree to match the pointed-to commit
    repo.head.reset(index=True, working_tree=True)

    # To detach your head, you have to point to a commit directy
    repo.head.reference = repo.commit('HEAD~5')
    assert repo.head.is_detached
    # now our head points 15 commits into the past, whereas the working tree
    # and index are 10 commits in the past

The previous approach would brutally overwrite the user’s changes in the working copy and index though and is less sophisticated than a git-checkout. The latter will generally prevent you from destroying your work. Use the safer approach as follows.

    # checkout the branch using git-checkout. It will fail as the working tree appears dirty
    self.failUnlessRaises(git.GitCommandError, repo.heads.master.checkout)
    repo.heads.past_branch.checkout()

Or, just below that: Using git directly In case you are missing functionality as it has not been wrapped, you may conveniently use the git command directly. It is owned by each repository instance.

    git = repo.git
    git.checkout('HEAD', b="my_new_branch")         # create a new branch
    git.branch('another-new-one')
    git.branch('-D', 'another-new-one')             # pass strings for full control over argument order
    git.for_each_ref()                              # '-' becomes '_' when calling it

And simply do the git.checkout() approach

Upvotes: 4

Related Questions