Last active
February 7, 2024 05:59
-
-
Save mgaitan/ba1e4e252b90a7fd4a4eb9e1742e94fb to your computer and use it in GitHub Desktop.
List or checkout recently used branches in git
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
List the most recent branches you have been working on, and switch any of them. | |
# Install | |
Put this file somewhere in your PATH, and set execution permissions. | |
Git will recognize it as the "recent-branches" subcommand. | |
# Usage | |
Without positional argument, it shows the 10 most recently used branches. | |
You can pass -n <number> to see more. | |
$ git recent-branches | |
1 - feature/EN-634 | |
2 - feature/en-583_3 | |
3 * master | |
4 - HOTFIX/spotify | |
5 - tests_factories | |
6 - feature/en-583_2 | |
7 - _prod/workers/orders_py3 | |
8 - prueba | |
9 - _prod/workers/products_py3 | |
10 - staging | |
Passing a number will checkout the branch listed in that position. | |
$ git recent-branches 5 | |
Switched to branch 'tests_factories' | |
Your branch is up to date with 'origin/tests_factories'. | |
If `git sw` ("smart switch" command) is available, it will be used. Otherwise, standard `git switch` will be tried. | |
See also https://gist.github.com/mgaitan/d9a3523d79cd5f9fbfd626f646f0560b | |
Note: In the list, the row with "*" (instead "-") is the current branch. | |
""" | |
import argparse | |
import re | |
import subprocess | |
from collections import OrderedDict | |
pattern = re.compile(r"checkout: moving from ([A-Za-z0-9_\/\-\.]+) to") | |
parser = argparse.ArgumentParser(prog="git recent-branches", description=__doc__.split("\n")[1]) | |
parser.add_argument("index", type=int, nargs="?", help="Move to the i-th branch in the list") | |
parser.add_argument("command", nargs="*", help="If given, run commands after switching and return to the current branch") | |
parser.add_argument("--limit", "-n", type=int, default=10, help="Show until the n-th branch") | |
parser.add_argument("--force", "-f", action="store_true", help="Force checkout") | |
args = parser.parse_args() | |
output = subprocess.check_output(["git", "reflog"], text=True) | |
branches = list(OrderedDict.fromkeys(re.findall(pattern, output)).keys()) | |
def switch_branch(branch_name, force=False): | |
use_sw = subprocess.call(["git", "sw"], stderr=subprocess.DEVNULL) == 2 and not force | |
cmd = ["git", "sw" if use_sw else "switch"] | |
if force: | |
cmd.append("-f") | |
cmd.append(branch_name) | |
subprocess.call(cmd) | |
current_branch = subprocess.check_output(["git", "branch", "--show-current"], text=True).strip() | |
if args.index: | |
target_branch = branches[args.index - 1] | |
# Switch to the target branch | |
switch_branch(target_branch, args.force) | |
# Execute the extra command if provided | |
if args.command: | |
subprocess.call(" ".join(args.command), shell=True) | |
# Switch back to the original branch | |
switch_branch(current_branch, args.force) | |
else: | |
for i, branch in enumerate(branches[: args.limit], 1): | |
print(f"{i} {'*' if current_branch == branch else '-'} {branch}") |
@pzelnip, thanks for the idea. I've just implemented it, with a default to top 10 most recently used branches
Nice!
I forked and added it to ask to switch branch
https://gist.github.com/alvarmaciel/884660733fdb7c6ad9603ceb23d239ca
why not simply use fzf
git switch `git branch | fzf| tr -d '[:space:]'`
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Love this idea, would be nice to have a way to say only show the top n branches. Ie something like:
to show the 5 most recent, rather than always show all. I have a few repos I interact with where there's a large number of branches, but only interact with a small handful.