Create an Interactive Bash Command for searching and checking out Git Branches on the Terminal using fzf
Tags: git, fzf, productivity, bash
Published: 2020-04-25 15:32:49

---
title: Create an Interactive Bash Command for searching and checking out Git Branches on the Terminal using fzf
published: true
cover_image: https://cdn.dribbble.com/users/1784988/screenshots/5167056/65.jpg
description: A command for interactively searching, checking out, and copying names of git branches on the Terminal using fzf 
tags: git, fzf, productivity, bash
---
*✏️ Cover art by Michael Rayback on [Dribble](https://dribbble.com/shots/5167056-Two-Branches)*

---

Git is an essential and powerful tool for any software developer. As part of your developer workflow, you might find yourself juggling between different projects and features all the time.

Given so, it's very hard to keep track of all the names of the branches between projects, especially when coming back to it after some time. So one common cumbersome procedure is looking up the name of the branch you want to get on that specific project and `git checkout` to it.

To achieve so, you first need to get all the branch names of the current project. Fortunately for us, `git` has a command for this, [**for-each-ref**](https://git-scm.com/docs/git-for-each-ref). What it does is iterate over all the references,  which is a readable name that points to the SHA-1 ids of git artifacts (e.g commits), given a pattern. For example, getting `refs/heads` returns a list of all the references of the head commits for each branch.

You can iterate on these references to print all the branches on the terminal by using the following command:

```bash
git for-each-ref --sort='authordate:iso8601' --format='%(authordate:relative)%09%(refname:short)' refs/heads
```
<figcaption>Figure 1: command for showing all the git branches ordered by descendent author-date</figcaption>

Of course, you can format and sort the results however you like. The next step would be to be able to interact with that list of branches, like selecting one, copying one, searching, and/or filtering the results. 

A pretty useful command for that is the well-known `grep`, which allows us to find patterns in the results. For example, we could chain the output of the branches command to `grep pattern` to search for branches that match the pattern.

I want to only see the branches which are prefixed with `fix` because I want to come back to fix that pesky bug? no problem, `git branches | grep fix` would do the filtering (pst, adding an [alias](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases) to the branches command is pretty useful). Then you can copy the branch name and check out to it

... But what if we want to interactively filter the branches and navigate through them, as well as binding keyboard commands to actions? (to, for example, check out to a branch using enter!)... you can easily do that with `Fzf`.

### Introducing Fzf

[Fzf](https://github.com/junegunn/fzf) is a `grep` on steroids. According to the description, it is a `general-purpose command-line fuzzy finder`.

{% github junegunn/fzf %}

`Fzf` grabs the output of any command, being it a list, processes, text... and lets you search and filter these results interactively and navigate through them. You can also assign key bindings to commands on your search.

With it, we can search and navigate through any directory easily and look for files, also adding some key bindings e.g opening the file in `vscode` when clicking enter and copying the filename path with tab.

```bash
ls | fzf --preview 'bat --style=numbers --color=always {}' --bind 'enter:execute(code {}),tab:execute-silent(echo {} | pbcopy)+abort' | head -100
```
<figcaption>Figure 2: command for searching and navigating through a directory with key bindings using fzf</figcaption>

![Output of the ls command using fzf](https://dev-to-uploads.s3.amazonaws.com/i/01g6p5q5p9l88qt1kufe.png)
<figcaption>Figure 3: output of the ls command using fzf</figcaption>

The above example uses [bat](https://github.com/sharkdp/bat) instead of `cat` for previewing files, as it includes some nice features like syntax highlighting and also shows modifications on files by integrating with git.

{% github sharkdp/bat %}

### Creating the interactive branch navigator with Fzf

With the `fzf` command in place, we can [pipe](https://linuxhint.com/bash_pipe_tutorial/) our `git branches` command *[Fig. 1]* to the `fzf` part of *[Fig. 2]* with some tweaking of the key bindings, and that will allow us to filter, copy and check out branches, just like that:

```bash
git for-each-ref --sort='authordate:iso8601' --format='%(authordate:relative)%09%(refname:short)' refs/heads | fzf --tac --bind 'enter:execute(echo {} | rev | cut -f1 | rev | xargs git checkout)+abort,tab:execute-silent(echo {} | rev | cut -f1 | rev | pbcopy)+abort'
```
<figcaption>Figure 4: command for interactively searching git branches,checking them out by pressing `enter` and copying the branch name by using `tab`</figcaption>

You can then bind the command to some git alias in `~/.gitconfig`, I have it assigned to `git brs`.

![git alias for the command](https://dev-to-uploads.s3.amazonaws.com/i/whas4nql6bxmylrjwhzu.png)
<figcaption>Figure 5: assigning a git alias for the command</figcaption>

`Fzf` includes numerous built-in key bindings as exiting with escape or navigating with scrolling/arrows, to name a couple. Try extending the command by adding more key bindings that fit your workflow!

Here's a short example of the command in action:

![interactive branch navigation command example](https://i.imgur.com/Pn43VZz.gif)
<figcaption>Figure 6: interactive branch navigation command example on the terminal</figcaption>

That's it! ✨

---

*And you, what other amazing `fzf` commands do you use, or would you create to improve your development workflow?*