git checkout last branches

I use git feature branches while working and when reviewing/integrating them into the main development branch I often need to quickly change between them a lot. Git offers a shortcut to jump to the last branch before the current one with: $ git checkout -

That is certainly helpful, but what if I want to jump to the 2nd-last branch? Afaik there is no builtin function for that, but since git is really just a bunch of commandline utilities it is not that hard to write a wrapper with bash or Python that does what we want. All actions like switching branches are logged in a file named reflog; we can parse and analyze that file to detect the last n-branches.

alias gol=source ~/git_checkout_last_branches.sh

#!python
import re
import subprocess
import sys

REFLOG_LINES = 1000
MAX_RESULTS = 10
DEFAULT_CHECKOUT = 2  # AKA last branch before the current one. 

regex = re.compile(r"checkout: moving from (?P<old>.+)? to (?P<new>.+)")
reflog = subprocess.check_output(["git", "reflog", "show", "-n",
                                  str(REFLOG_LINES)])
last_branches = []
matches = regex.findall(reflog)
for origin, target in matches:
    if origin not in last_branches:
        last_branches.append(origin)
options = {}
for i, branch in enumerate(last_branches[:MAX_RESULTS]):
    i += 1
    options[i] = branch
    print("{i}) {branch}".format(**locals()))
print("")

chosen = raw_input("Which branch do you want to checkout ({}): "
                   .format(DEFAULT_CHECKOUT))
if not chosen:
    chosen = DEFAULT_CHECKOUT
try:
    chosen = int(chosen)
except ValueError:
    print("You must enter a number.")
    sys.exit(1)
try:
    branch = options[chosen]
except KeyError:
    print("Incorrect index.")
    sys.exit(1)
print(subprocess.check_output(["git", "checkout", branch]))

This will give us a simple prompt where we can select one of the last branches by specifying its index:
git_checkout_last

The following script is a slightly more interactive version that uses a cool package named asker to choose an option with the arrow keys. It also supports filtering the list by typing some characters ($ pip install asker).

alias gol=source ~/git_checkout_last_branches_v2.sh

#!python
import re
import subprocess
import sys

from asker import ask

REFLOG_LINES = 1000

regex = re.compile(r"checkout: moving from (?P<old>.+)? to (?P<new>.+)")
reflog = subprocess.check_output(["git", "reflog", "show", "-n",
                                  str(REFLOG_LINES)])
last_branches = []
matches = regex.findall(reflog)
for origin, target in matches:
    if origin not in last_branches:
        last_branches.append(origin)

options = {}
for i, branch in enumerate(last_branches[:10]):
    i += 1
    options[i] = branch

choice = ask("Which branch do you want to checkout? ",
             choices=options.values(),
             labels=options.values())

print(subprocess.check_output(["git", "checkout", choice]))

This is what we get:
git_checkout_last_v2

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s