3 ms·
tl;dr Please ignore, just me working through a Python+pygit2 problem. I solved it in a grandchild comment. I had so much trouble trying to map my intuited/ment
by bloopernova 3y ago
tl;dr Please ignore, just me working through a Python+pygit2 problem. I solved it in a grandchild comment.
I had so much trouble trying to map my intuited/mental model of git onto pygit2 that I gave up and just used the git module.
I wanted to automate a fairly simple thing in Python as opposed to bash+commands. My reasoning being that I wanted to do it "right" and be a Big Programmer Real Boy(tm). I just wanted to create a branch remotely in Github, pull the repo, and checkout the new branch. I got stuck going in circles trying to figure out why I was always left in detached HEAD state because I didn't understand exactly what git was doing during a checkout.
# repo has already been pulled
if os.path.exists(repo_path):
local_repo = git.Repo(path=repo_path)
self.log.debug(f"current branch: {local_repo.active_branch.name}")
local_repo.git.checkout(branch_name)
That's super easy and is much the same as running the commands in the shell or in a bash script.
Of course, I've lost my poor implementation using pygit2, so I'll add that later if I find it. Thankfully there's a good discussion surrounding the issue I encountered in this excellent "roll your own git in Python", which doesn't use pygit2, but the concepts are the same: https://www.leshenko.net/p/ugit/#checkout-switch-branches https://www.leshenko.net/p/ugit/#checkout-switch-branches
- bloopernova 3y agoThis isn't asking someone else to make this work, it's more of a caution to convince folks like me to just use "import git" rather than pygit2: So something like this was what I expected to work, but leaves the repo in detached head state: import pygit2 def checkout_branch(path, branch_name): repo = pygit2.Repository(path) branch_ref = repo.lookup_reference(f"refs/remotes/origin/{branch_name}") print(f"{branch_ref.name}") repo.checkout(branch_ref) The branch_ref.name prints "refs/remotes/origin/test" but git status says "HEAD detached at origin/test" So I'm probably feeding the wrong thing into repo.checkout, but I'm honestly not sure what else it should be. Funnily enough, git itself tries to do the right thing if pulled in a detached head state: From https://github.com/testorg/example * [new branch] test -> origin/test You are not currently on a branch. Please specify which branch you want to merge with. See git-pull(1) for details. git pull <remote> <branch>
- deleted 3y ago[deleted]
- bloopernova 3y agoHa, and of course just messing around gets me something that actually works. There always seems to be just one more stackoverflow thread to read that has the real answer: https://stackoverflow.com/questions/68435607/how-to-clone-master-and-checkout-another-branch-in-pygit2-without-detached-head https://stackoverflow.com/questions/68435607/how-to-clone-ma... (found via Kagi which I wasn't using before, and the search "pygit2 detached head") def checkout_branch(path, branch_name): repo = pygit2.Repository(path) main_branch = repo.lookup_branch("main") print(f"Main branch upstream: {main_branch.upstream_name}") if branch_name not in repo.branches.local: print(f"Branch {branch_name} not found in local branches") remote_branch = "origin/" + branch_name if remote_branch not in repo.branches.remote: raise SystemExit(f"Branch {remote_branch} not found in remote branches") (commit, remote_ref) = repo.resolve_refish(remote_branch) repo.create_reference("refs/heads/" + branch_name, commit.hex) branch = repo.lookup_branch(branch_name) print(f"Branch name: {branch.name}") repo.checkout(branch) print(f"Is branch head? {branch.is_head()}") (commit, branch_remote) = repo.resolve_refish("origin/" + branch_name) print(f"Remote branch: {branch_remote.name}") branch.upstream = branch_remote With git reflog telling me the right thing: d44aedc (HEAD -> test, origin/test) HEAD@{0}: checkout: moving from main to test And git push has the remote branch already set. I wish there was a pair programmer AI that you had to explain stuff to. That would enable the "by explaining it, I solved it" phenomenon.
- Izkata 3y ago> I wish there was a pair programmer AI that you had to explain stuff to. That would enable the "by explaining it, I solved it" phenomenon. It's called rubber duck debugging, named for having an actual rubber duck at your desk you'd talk to.