Skip to main content

Command Palette

Search for a command to run...

How I Work on Four Git Branches at the Same Time

Git Worktrees Explained: What They Are and Why They Exist

Updated
7 min readView as Markdown
How I Work on Four Git Branches at the Same Time

If you've been using Git for a while, chances are you've gone through this.

You're deep into implementing a feature. Everything is going well. You have a few uncommitted changes, your development server is running, and you're finally in the zone.

Then someone pings you.

"Hey, can you quickly fix this production bug?"

Great.

Now your flow is interrupted.

You open the terminal and start the ritual.

git status 
git add . 
git stash 
git checkout main 
git pull 
git checkout -b hotfix/login

You fix the bug.

Commit.

Push.

Now it's time to get back to your feature.

git checkout feature/report-generator 
git stash pop

Hopefully nothing conflicts.

Hopefully you didn't forget what was in your stash.

Hopefully you don't accidentally commit the hotfix into your feature branch.

This isn't a Git problem. It's a workflow problem.

And it doesn't stop with production bugs.

Maybe you need to:

  • Review a teammate's pull request.

  • Experiment with another implementation.

  • Compare two branches.

  • Test something on the release branch.

  • Try a framework upgrade without affecting your current work.

Every time, you switch branches.

Every time, you break your flow.

Then I discovered Git Worktrees.


There Has To Be A Better Way

Imagine opening another VS Code window.

Another terminal.

Another branch.

Without touching your current one.

No stashing.

No switching.

No cloning the repository again.

Just another folder.

That's exactly what Git Worktrees allow you to do.


What Is Git Worktree?

Git Worktree allows you to have multiple branches checked out simultaneously.

Let's say your current repository looks like this.

Projects/ 
└── car360/ 
      └── feature/report-generator

A production bug comes in.

Instead of switching branches, create another worktree.

git worktree add -b hotfix/login ../car360-hotfix main

Now your project structure becomes

Projects/ 
├── car360/ 
│     └── feature/report-generator 
└── car360-hotfix/ 
      └── hotfix/login

Open each folder in a separate VS Code window.

Run your development server inside each.

Each folder has its own working files, terminal, and Git status.

Yet they're all backed by the same repository.


Why Was Git Worktree Created?

Many developers think Git Worktrees exist only for fixing production bugs.

That's just one use case.

Modern software development isn't linear anymore.

You're rarely working on a single task from start to finish.

A typical day might involve

  • Building a new feature

  • Reviewing someone's pull request

  • Fixing a production issue

  • Testing against a release branch

  • Experimenting with a new architecture

  • Trying a framework upgrade

Without Worktrees, you're constantly switching contexts.

Git Worktrees were introduced to make parallel development easier.

Instead of moving between branches, each task gets its own workspace.


Under The Hood

At first glance, Worktrees look like another copy of your repository.

But that's not what actually happens.

Suppose your repository looks like this.

car360/
├── .git/
├── src/
├── package.json
└── ...

After creating a worktree

git worktree add -b hotfix/login ../car360-hotfix main

you get

car360/
├── .git/
├── src/
└── ...

car360-hotfix/
├── .git
├── src/
└── ...

Notice something?

The second repository doesn't even have a .git directory.

It has a tiny .git file.

Inside that file is something like

gitdir: /Users/ananthu/projects/car360/.git/worktrees/car360-hotfix

That file simply points back to the original repository.

Both worktrees share

  • commit history

  • object database

  • remotes

  • tags

  • branches

Each worktree has its own

  • working directory

  • HEAD

  • staging area

  • uncommitted changes

This is why changes in one worktree don't interfere with another.


Isn't This Just Cloning The Repository Twice?

This was my first question too.

At first glance, they look almost identical.

Projects/
├── car360/
└── car360-copy/

or

Projects/
├── car360/
└── car360-hotfix/

In both cases, you end up with two folders containing the same project.

So what's the difference?

Cloning the repository twice

When you clone a repository twice, you actually create two completely independent Git repositories.

Projects/
├── car360/
│   └── .git/
│
└── car360-copy/
    └── .git/

Each clone has its own:

  • Git object database

  • References (refs)

  • Remote-tracking branches

  • Configuration

  • Hooks

  • Staging area (index)

  • Working directory

Although both clones start with the same commit history, each stores its own copy of that history and manages it independently.

If you run

git fetch

inside car360, only that repository gets updated.

car360-copy has no idea that new commits or branches exist until you fetch there as well.

They're completely separate repositories that just happen to have started from the same source.


Git Worktrees

Now let's look at a worktree.

Projects/
├── car360/
│   └── .git/
│
└── car360-hotfix/
    └── .git

Notice something?

The second one doesn't even have a .git directory.

It has a tiny .git file.

If you open it, you'll see something similar to:

gitdir: /Users/ananthu/projects/car360/.git/worktrees/car360-hotfix

That file simply tells Git,

"My repository lives over there."

Both folders are connected to the same underlying Git repository.

They share:

  • Commit history

  • Object database

  • Branch references

  • Tags

  • Remotes

  • Hooks

  • Configuration

Each worktree only has its own:

  • Working directory

  • HEAD

  • Staging area (index)

  • Uncommitted changes

This means if you run

git fetch

from any worktree, every other worktree immediately sees the updated remote branches because they're all using the same Git metadata.


Why It's Surprisingly Optimised

The coolest part about Git Worktrees is how lightweight they are.

Git doesn't duplicate

  • commits

  • history

  • remotes

  • object database

  • tags

Only the working files are created again.

Imagine your repository history takes up 3 GB.

Your source code occupies another 200 MB.

Cloning twice might roughly consume

3.2 GB
+
3.2 GB

With Worktrees

3 GB
+
200 MB
+
200 MB

because the heavy Git database is shared.

You fetch once.

Everyone sees it.

You commit once.

The commit is stored in the same object database.

It's surprisingly efficient for something that feels like multiple repositories.


My Favourite Workflow

Nowadays my projects usually look something like this.

Projects/
├── car360/
│   └── feature/report-generator
│
├── car360-hotfix/
│   └── hotfix/login
│
├── car360-review/
    └── teammate/payment-refactor

Each folder is opened in its own VS Code window.

Each has its own terminal.

Each can run

npm dev

simultaneously.

No switching branches.

No stashing.

No interrupting my flow.


Commands You'll Actually Use

Create a new worktree with a new branch

git worktree add -b feature/new-ui ../car360-new-ui

Create a worktree for an existing branch

git worktree add ../car360-review teammate/payment-refactor

List all worktrees

git worktree list

Remove a worktree

git worktree remove ../car360-review

Delete the branch if you no longer need it

git branch -d teammate/payment-refactor

Clean up stale worktree metadata

git worktree prune

A Few Things To Remember

The same branch cannot be checked out in two worktrees simultaneously.

Removing a worktree does not delete the branch.

Deleting the folder manually isn't recommended.

Always use

git worktree remove

to let Git clean everything up properly.


Final Thoughts

Git Worktrees have been part of Git for years.

Yet they're still one of the least talked-about features.

Once I started using them, I stopped thinking of Git as "one repository, one working directory."

Instead, each task got its own workspace.

I no longer stash my changes just because someone asked for a quick fix.

I no longer stop my development server to switch branches.

I simply open another folder and continue working.

Sometimes, the best productivity tools aren't new frameworks or AI assistants.

They're features that have quietly existed for years, waiting for someone to discover them.

Git Worktrees are one of those features.


References