# Git Worktrees Are Underrated

Published: March 16, 2026
Tags: git, cli, productivity, rust, opensource

Git worktrees let you work on multiple branches at once without stashing or losing context. Here's how they changed my workflow and how I manage them.

If you've ever stashed half-finished work to review a PR, or lost a train of thought switching branches, you should know about git worktrees. They've been in git since 2015, but most developers I talk to have never heard of them.

## The problem with branches

The standard git workflow is linear. You're on a branch, you need to context-switch, so you stash your changes (or worse, make a throwaway commit), switch branches, do your thing, switch back, and pop the stash. If you're lucky, nothing conflicts.

This gets worse when you're juggling multiple things at once. Reviewing a colleague's PR while your feature branch is mid-refactor. Running tests on one branch while coding on another. Hotfixing production while your main work sits frozen.

A git repository has one working directory. One branch checked out at a time. Everything else has to wait.

## Worktrees

Git worktrees let you check out multiple branches simultaneously, each in its own directory. They share the same `.git` history and objects, so you're not cloning the entire repo, but each one has its own working directory and index.

```sh
git worktree add ../feat-login feat/login
```

Now `feat/login` is checked out in `../feat-login`. You can open it in a separate editor window, run tests there, or just let it sit while you work on something else.

When you're done:

```sh
git worktree remove ../feat-login
```

## Why nobody uses them

If worktrees are so useful, why aren't they more popular? I think it comes down to two things.

First, the directory problem. Every time you create a worktree, you have to pick a path. There's no convention for where they go. After a week you end up with directories scattered across your filesystem: `../feat-login`, `~/tmp/hotfix-auth`, `../../pr-review`. Good luck remembering where anything is.

Second, there are no ergonomics. You can't easily list your worktrees with status info, cd into one quickly, or run something like `npm install` in the new directory after checkout. The raw git commands work, but they don't make worktrees feel like a real workflow.

These aren't fundamental problems with worktrees. They're tooling gaps. That's why I built [arbor](https://github.com/morellodev/arbor).

## A better workflow with arbor

Arbor is a CLI that manages git worktrees. It keeps them organized in a central directory (`~/.arbor/worktrees/`) and handles the stuff that plain git doesn't.

```sh
# Clone a repo (sets up a bare repo + default branch worktree)
arbor clone user/my-app

# Create a worktree for a new feature
arbor add feat/login

# Shell integration auto-cds you into the worktree
# You're now in ~/.arbor/worktrees/my-app/feat-login

# Need to review a PR? Open another worktree
arbor add fix/auth-bug

# See all your worktrees with dirty/clean status
arbor status
```

Every worktree for `my-app` lives under `~/.arbor/worktrees/my-app/`. Branch slashes become dashes in directory names, so the filesystem stays tidy. When you're done with a branch:

```sh
arbor rm -d feat/login
```

That removes the worktree and the local branch in one step.

## What makes it stick

I've been using worktrees for a while, but I kept falling off because of the friction. A few things in arbor made the difference for me.

Shell integration. `arbor init` sets up a wrapper so that `arbor add` and `arbor switch` automatically cd you into the worktree directory. Without it you create the worktree and then have to `cd` into it yourself every single time, which gets old fast.

Post-create hooks. You can add an `.arbor.toml` to your repo:

```toml
[hooks]
post_create = "npm install"
```

Every new worktree gets its dependencies installed automatically. You can chain commands too:

```toml
[hooks]
post_create = ["npm install", "cp .env.example .env"]
```

And `arbor status --all` shows the state of every worktree across all your repos, which is nice for a quick scan before you call it a day.

## Where I use them most

PR reviews. `arbor add` the branch, review it in a separate editor window, remove it when done. My own work is untouched.

Long test suites. Tests running on one branch, coding on another. No waiting around.

Hotfixes. `arbor add hotfix/critical`, fix it, push it, remove it. Back to what I was doing.

Comparing behavior. Two worktrees open side by side, one on `main` and one on my feature branch. Way easier than switching back and forth.

Big migrations. Upgrading a framework to a new major version in a worktree while the rest of the team keeps shipping from `main`. No half-broken build blocking anyone.

## Try it

Arbor is open source, written in Rust. Install with Homebrew:

```sh
brew install morellodev/tap/arbor
```

Or grab a binary from the [releases page](https://github.com/morellodev/arbor/releases/latest).

Run `arbor init` after installing to set up shell integration. Takes about 30 seconds.

If you've never tried worktrees, give them a shot. And if you have but gave up because of the directory mess, this might be worth another look.

The repo is at [github.com/morellodev/arbor](https://github.com/morellodev/arbor).
