Search code examples
pythongit

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).


Solution

  • 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