Interactive Git Checkout — Creating a simple git branch switcher in Node

Pete Cook
Pete Cook
Apr 18, 2019 · 3 min read

Tired of constantly using git checkout to switch between branches? Let’s write a simple branch switcher in Node.

Image for post
Image for post
Here’s one I made earlier

Previously I’ve used git branch --sort=-committerdate aliased to gbs as a reminder of the branches I’ve been working on recently. The first thing to do is use Node’s child_process to run this command for us.

const { promisify } = require('util')
const exec = promisify(require('child_process').exec)
async function run () {
const branches = await exec('git branch -v --sort=-committerdate')
}
run()

We’re using Node’s promisify utility to create a version of exec that we can use with async/await. If you are unfamiliar with async/await I encourage you to get familiar with it, because it’s awesome.

branches will be an object containing stdout and stderr strings that give us the result of running the command in a child process. stdout will be a string we can split by newlines to get our branches.

const choices = branches.stdout
.split(/\n/)
.filter(branch => branch.trim())
.map(branch => {
const pattern = /([* ]) +([^ ]+) +(.+)/
const [, flag, value, hint] = branch.match(pattern)
return { value, hint, disabled: flag === '*' }
})

Here we parse the raw output of the git branch command into an array we can pass into the prompts library later on. The filter function uses trim() to remove any empty lines. The map function uses a regular expression to parse the branch information. We disable any branches with a * flag, as this is the currently checked out branch.

Notice how we added -v to the git branch command? This gives us information about the current commit of each branch, and how far ahead it is from the remote version. We can use this information in the next step.

const prompts = require('prompts')const { branch } = await prompts({
type: 'select',
name: 'branch',
message: 'Switch branch',
choices,
hint: choices[0].hint,
warn: 'current branch',
onState ({ value }) {
this.hint = choices.find(c => c.value === value).hint
}
})

We’re using prompts to output a very simple command line select list to let users select a branch. Note the use of onState to set the hint using the extra branch information we gathered before. The result of prompts is an object of user input values according to its name. We’re using object destructuring to grab branch straight from the resulting object. The last step is to simply run git checkout using the selected branch.

await exec(`git checkout ${branch}`)

This will work, but unfortunately gives us no feedback from the git command about if the checkout was successful or not. A bit of extra work is required.

async function checkout (branch) {
const { stdout, stderr } = await exec(`git checkout ${branch}`)
process.stdout.write(stdout)
process.stderr.write(stderr)
}

Here we essentially pipe the output of git checkout through to the terminal. The command outputs useful information in both stdout and stderr, even after a successful checkout, so we use both.

I’ve put a more complete version of the script on GitHub, and published an npm module which you can use right now:

npm install --global git-checkout-interactive

Then, switching branches becomes as simple as:

gci

OneHub | Product Engineering

Creating the technology that powers the OneHub product line

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store