# 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.

```shell
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.

```shell
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](https://git-scm.com/docs/git-worktree).

* * *

## 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.

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

A production bug comes in.

Instead of switching branches, create another worktree.

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

Now your project structure becomes

```plaintext
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.

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

After creating a worktree

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

you get

```plaintext
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

```plaintext
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.

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

or

```plaintext
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**.

```plaintext
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

```shell
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.

```plaintext
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:

```plaintext
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

```plaintext
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

```plaintext
3.2 GB
+
3.2 GB
```

With Worktrees

```plaintext
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.

```plaintext
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

```plaintext
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

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

Create a worktree for an existing branch

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

List all worktrees

```plaintext
git worktree list
```

Remove a worktree

```plaintext
git worktree remove ../car360-review
```

Delete the branch if you no longer need it

```plaintext
git branch -d teammate/payment-refactor
```

Clean up stale worktree metadata

```plaintext
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

```plaintext
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

*   [https://git-scm.com/docs/git-worktree](https://git-scm.com/docs/git-worktree)
    
*   https://medium.com/cars24/boost-your-productivity-with-git-worktrees-7093a51c6af9
