Skip to main content

One Line Fuzzy Find for Git Worktree

·693 words·4 mins·
fzf git awk bash
Table of Contents
❤️ It's great to see you here! I'm currently available on evenings and weekends for consulting and freelance work. Let's chat about how I can help you achieve your goals.


"Magnifying Glass" by Birmingham Conservation Trust is licensed under CC BY 2.0 .

The Backstory

I’ve written on fuzzy matching with fzf before. I’ve covered adding tab completion to an existing command, using fzf to get a file preview windows and combining tab completion and preview windows to improve an existing command.

Those are helpful things to do and I use them all the time, but today I’d like to cover a much simpler use case – a one-liner to allow you to use fuzzy matching to navigate git worktrees. If you’d like to read up on why you may want to use worktrees in git, I’ve covered that in 4 Strategies for Context Switching in Git.

Just Show Me the Command

You’ve heard enough from me by this point. Let’s try the command below. If you’re playing along at home, you’ll need to be inside a git repository.

Note: if you’re in a repository where you have not explicitly created a worktree, you’ll only get one result in the list, since git repositories by default exist in a worktree.

cd "$(git worktree list | fzf | awk '{print $1}')"

If you have more than one worktree in your repository, you should see something like this:

   /Users/olaf/.worktree/Perl-Advent/oalders/santa-picks-nits  c312df9 [oalders/santa-picks-nits]
   /Users/olaf/.worktree/Perl-Advent/oalders/perlimports       a8884db [oalders/perlimports]
>> /Users/olaf/Documents/github/perladvent/Perl-Advent         2a3d745 [oalders/new-index.html]
  3/3 (0) ───────────────────────────────────────────────────────────────────────────────────────────────────

Once you begin typing, the matching begins:

   /Users/olaf/.worktree/Perl-Advent/oalders/perlimports       a8884db [oalders/perlimports]
   /Users/olaf/Documents/github/perladvent/Perl-Advent         2a3d745 [oalders/new-index.html]
>> /Users/olaf/.worktree/Perl-Advent/oalders/santa-picks-nits  c312df9 [oalders/santa-picks-nits]
  3/3 (0) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
> nit

At this point a return will cd you to the worktree of your choice, or you can opt out via ctrl-c.

Let it Live in a Function

To make this easier to use, you can store it in a function:

cd_worktree() {
    cd "$(git worktree list | fzf | awk '{print $1}')"

If this is in your .bashrc or some other place that gets sourced by your environment, you can have access to this selector via the function name directly at the command line:

$ cd_worktree

Or Put it in a Script

This works too:


set -eu -o pipefail

cd "$(git worktree list | fzf | awk '{print $1}')"

How About an alias?

You might find a way to mash this into an alias, but I should point out the following:

  1. The bash man page says that

For almost every purpose, shell functions are preferred over aliases

  1. You’ll likely have a linter complaining about a positional parameter in an alias. And yes, I realize that the $1 here is an awk thing rather than a bash thing, but my linter doesn’t know that.

Having said that, how you handle this is entirely up to you. If someone tells that using an alias means you’re wrong, you can kindly tell them to get stuffed, because there’s certainly more than one way to do it.

How it Works

Let’s break this down. Basically there are 4 things happening here:

cd "$(git worktree list | fzf | awk '{print $1}')"
  1. git worktree list is being called
  2. All of the output from git worktree list is piped directly to fzf. At this point nothing happens until there is some input from the keyboard
  3. Once there is a carriage <return>, the entire selected line is handed off to awk, which splits the line on spaces and returns the first element in the list ($1). That element is the path to the root directory of the worktree.
  4. The worktree path is provided to the cd command and now you are on your way

Build Something Fun

What I like about this example is that it’s not particularly complicated, but it has enough moving parts that it merits some discussion. You could build something similar for switching between git branches, tmux sessions or something way better that I haven’t even thought of.

Because it fits on one line you can even keep it as a handy snippet that you copy/paste, if you don’t feel like making shell functions available or putting the one-liner into a script or whatever.

I hope you have fun with this. Please let me know if you build something you’d like to share with me.


Autocorrecting my Git Commands
·598 words·3 mins
git bash autocorrect
Find and Fix More Typos
·1402 words·7 mins
fzf linting Neovim precious tidying typos VS Code
4 Strategies for Context Switching in Git
·1257 words·6 mins
git worktree