Skip to main content

git/gpr

1#!/usr/bin/env python3
3import subprocess
4import webbrowser
7def git(*args: str) -> str:
8 """
9 Run a Git command and return the output.
10 """
11 cmd = ["git"] + list(args)
12 return subprocess.check_output(cmd, text=True).strip()
15def get_parent(commit_id: str) -> str:
16 """
17 Return the commit ID of the parent of this commit.
18 """
19 return git("log", "--pretty=%P", "-n", "1", commit_id)
22def get_remote_branches(commit_id: str) -> list[str]:
23 """
24 Return a list of remote branches where this commit is the tip.
25 """
26 branches = git(
27 "for-each-ref",
28 "--format=%(refname:short)",
29 "refs/remotes/",
30 "--points-at",
31 commit_id,
32 ).splitlines()
33 return [b for b in branches if b != "origin"]
36def get_local_branches(commit_id: str) -> list[str]:
37 """
38 Return a list of local branches where this commit is the tip.
39 """
40 return git(
41 "for-each-ref",
42 "--format=%(refname:short)",
43 "refs/heads/",
44 "--points-at",
45 commit_id,
46 ).splitlines
49if __name__ == "__main__":
50 current_branch = git("rev-parse", "--abbrev-ref", "HEAD")
51 base_branch = "main"
53 commit = git("rev-parse", "HEAD")
54 for _ in range(5):
55 parent = get_parent(commit)
57 if rb := get_remote_branches(parent):
58 base_branch = rb[0].replace("origin/", "")
59 break
61 if lb := get_local_branches(parent):
62 if lb[0] == "main":
63 break
65 github_url = subprocess.check_output("_get_github_url", text=True).strip()
67 url = f"{github_url}/compare/{base_branch}...{current_branch}?expand=1"
68 webbrowser.open(url)