Karya Semi
HomeBlogSearchCategoriesAboutContact
Karya Semi

Less noise. More notes.

HomeBlogAboutContactPrivacy PolicyDisclaimer

© 2026 Karya Semi. All rights reserved.

XGitHubLinkedIn
  1. Home
  2. /Categories
  3. /Software Engineering

Streamline Parallel Feature Work with Git Worktree

Avoid stash conflicts. Leverage git worktree parallel development to manage multiple active branches at once. Eliminate context switching and deploy faster.

Dian Rijal Asyrof/August 28, 2026/7 min read
Illustration for Streamline Parallel Feature Work with Git Worktree

We have all been there. You are halfway through a complex feature branch. You have ten modified files, three failing TypeScript tests you are actively debugging, and a half-configured local database state. The slack notification sounds: a critical bug is live in production. You need to fix it immediately.

Your options look grim. You can run git stash, switch to main, write the patch, push it, switch back, and run git stash pop. This is one of the common Git mistakes that breaks your flow. Stashing clears your working directory, which forces your IDE to re-index the project. Your build cache gets invalidated. If you are working on a large codebase, you might spend ten minutes waiting for compilation pipelines to run again just to change a single line of code. Even worse, if you had untracked files or schema migrations in progress, stashing can leave your local environment in a broken state.

Another option is cloning the repository a second time into another folder. This works, but it wastes disk space. You end up with multiple copies of the entire project history. If you run git fetch in one folder, the other folder knows nothing about it until you pull again.

Git worktree solves this problem. It lets you run multiple working directories from a single local repository database. You can keep your feature branch open in one terminal pane, open a new directory for the hotfix in another, and write the patch without touching your active workspace.

How Git Worktree Works

Let's look at the mechanics. When you run a standard git clone, Git creates a directory containing two main components: the working tree (your project files) and the .git folder (the repository database).

A worktree is simply another checked-out copy of your repository, placed in a separate directory. Instead of creating a new .git database, the new directory contains a small .git file. This file acts as a pointer. It points directly back to the main repository database in your original folder.

Because both directories share the same database, they share the same history, branches, and stashes. If you run git fetch in your feature directory, the hotfix directory immediately sees the new commits. You do not need to push to GitHub or use local remotes to share code between them.

Setting Up Your First Worktree

Let's walk through the basic commands. Suppose you are working in a repository located at ~/projects/my-app. You are on a branch called feature-login.

To create a new workspace for a hotfix without disturbing your current files, run:

git worktree add ../my-app-hotfix main

This command does three things:

  1. Creates a new directory named my-app-hotfix one level up from your current folder.
  2. Checks out the main branch inside that directory.
  3. Links the directory to your main Git database.

Now you can open a new terminal tab, change directory to ~/projects/my-app-hotfix, and start working. Your IDE can open this folder separately. Your editor state in my-app remains untouched. Your modified files are still there, your tests are still in progress, and your build caches are safe.

If you need to create a new branch for the hotfix instead of checking out an existing one, use the -b flag:

git worktree add -b hotfix-security ../my-app-hotfix origin/main

This creates the hotfix-security branch based on origin/main and checks it out in the new directory.

Managing Worktrees

As you start using worktrees, you will need to keep track of them. To see all active directories linked to your database, run:

git worktree list

The output shows the absolute path of each worktree, the commit hash it is currently on, and the active branch name:

/Users/username/projects/my-app          a1b2c3d [feature-login]
/Users/username/projects/my-app-hotfix   e5f6g7h [hotfix-security]

Once you finish the hotfix, commit the changes, push them to the remote repository, and open your pull request. After that, you no longer need the temporary directory. You can remove it using the remove command:

git worktree remove ../my-app-hotfix

This command deletes the directory from your disk and cleans up the references inside the main .git folder.

If you manually delete the directory using the command line (rm -rf ../my-app-hotfix) or your file manager, Git will still think the worktree exists. It will show up when you run git worktree list. To clean up these dead references, run:

git worktree prune

This scans the database for worktrees whose directories no longer exist on disk and deletes their metadata.

The Bare Repository Workflow

Using sibling folders like ../my-app-hotfix works, but it creates an uneven structure. You have a "parent" directory (my-app) that contains the actual .git database, and several "child" directories scattered around it. If you accidentally delete my-app, you lose the Git database for all your worktrees.

To avoid this, you can use the bare repository pattern. A bare repository contains only the Git database and no working files. By cloning your project as a bare repository, you can treat all your active branches as equal worktrees.

Here is how to set up this workflow from scratch:

# Create a parent directory for the project
mkdir my-project
cd my-project
 
# Clone the repository as a bare repo into a hidden folder
git clone -bare git@github.com:username/repo.git .bare
 
# Tell Git where to find the database for commands run in the root
echo "gitdir: .bare" > .git

Now, your root directory my-project contains only the .bare database folder and a .git pointer file. You do not write code in this root directory. Instead, you create worktrees inside it for each branch you want to work on:

# Add a worktree for the main branch
git worktree add main
 
# Add a worktree for your current feature
git worktree add feature-billing

Your directory structure will look like this:

my-project/
├── .bare/            # The shared Git database
├── .git              # Pointer file
├── main/             # Worktree for the main branch
└── feature-billing/  # Worktree for feature development

This setup is clean. If you need a temporary hotfix, you create a folder inside my-project/hotfix. When you are done, you delete it. The main database remains untouched inside .bare.

Handling Dependency and Build Cache Overhead

One challenge of running multiple worktrees is managing dependencies. If you are working on a Node.js project, running npm install in three different worktrees will copy gigabytes of duplicate files to your disk.

To handle this, look at your package manager. If you use pnpm or Bun, this problem disappears. Both tools use global content-addressable storage. When you run pnpm install in a new worktree, it creates hard links to the global store instead of copying files. The installation takes seconds and uses virtually no extra disk space.

If you are stuck with npm or Yarn, you can use workspaces or configure your tools to share cache directories.

For compiled languages like Rust or Go, build artifacts can consume massive amounts of disk space. For example, a Rust target directory can easily grow to several gigabytes. If you compile the same project in three different worktrees, you will run out of disk space quickly.

You can solve this by configuring your build tools to share a single target directory. In Rust, you can set the CARGO_TARGET_DIR environment variable in your shell configuration:

export CARGO_TARGET_DIR="$HOME/.cache/cargo-target"

Alternatively, you can create a shared configuration file in your home directory or in each worktree. This forces Cargo to compile all dependencies to a central location, saving disk space and speeding up build times across different branches.

Working with IDEs

Modern editors handle worktrees well, but you need to adjust your workflow slightly. When using VS Code, open each worktree as a separate window. If you use the bare repository layout, you can open the root folder my-project as a workspace, or open individual directories like main and feature-billing depending on what you are doing.

JetBrains IDEs (IntelliJ, WebStorm, PyCharm) automatically detect Git worktrees. When you open a linked worktree folder, the IDE reads the .git file pointer and configures the version control integration automatically.

If you use terminal-based editors like Neovim, you can use plugins designed for worktrees, or simply rely on standard shell commands to jump between directories.

Important Limitations and Edge Cases

While Git worktree is powerful, it has a few rules you must follow.

First, you cannot check out the same branch in two different worktrees at the same time. If you try to run git worktree add ../another-dir main while main is already checked out in your main/ directory, Git will block the action with an error:

fatal: 'main' is already checked out at '/path/to/my-project/main'

This restriction exists to prevent data corruption. If you were allowed to modify files on the same branch in two places simultaneously, committing changes in one directory would invalidate the index of the other directory, leading to conflicts and lost work. If you need to work on the same logical branch, create a temporary branch pointing to the same commit:

git checkout -b feature-login-experiment origin/feature-login

Second, local configuration options are shared by default. If you run git config user.email "work@company.com" inside a worktree, that change applies to the shared .git database and affects all other worktrees.

If you need worktree-specific configurations-for example, using a different commit email for a specific branch-you must enable the worktree configuration extension:

git config extensions.worktreeConfig true

Once enabled, you can write configuration options that apply only to the current worktree by using the -worktree flag:

git config -worktree user.email "personal@email.com"

This writes the settings to a special configuration file located at .git/worktrees/<worktree-name>/config.worktree, keeping it separate from the main repository configuration.

Transitioning to Git Worktree

You do not need to switch your entire workflow overnight. Start by using worktrees for quick code reviews or testing pull requests. The next time you need to review a coworker's branch, instead of switching your current workspace, run git worktree add ../review-branch branch-name. Run the tests, check the code, delete the directory, and run git worktree prune.

Once you get used to the speed of keeping your primary workspace clean, you can experiment with the bare repository layout to organize your daily development.

DR

Dian Rijal Asyrof

Writes about useful AI tools, programming practice, and the craft of building reliable software.

Previous articleSecurity Risk Breakdown: Sweeping Permissions in Autonomous AI AssistantsNext articleImproving LLM Code Generation Quality using agent.md
Git WorktreeVersion ControlDeveloper ToolsProductivity
On this page↓
  1. How Git Worktree Works
  2. Setting Up Your First Worktree
  3. Managing Worktrees
  4. The Bare Repository Workflow
  5. Handling Dependency and Build Cache Overhead
  6. Working with IDEs
  7. Important Limitations and Edge Cases
  8. Transitioning to Git Worktree

On this page

  1. How Git Worktree Works
  2. Setting Up Your First Worktree
  3. Managing Worktrees
  4. The Bare Repository Workflow
  5. Handling Dependency and Build Cache Overhead
  6. Working with IDEs
  7. Important Limitations and Edge Cases
  8. Transitioning to Git Worktree

See also

Illustration for Long-Term Technical Impact of AI Coding Assistants on Senior Software Engineering
Programming/Aug 28, 2026

Long-Term Technical Impact of AI Coding Assistants on Senior Software Engineering

Measure ai coding impact expertise. Automated generation risks senior system design skills. Learn to balance speed with deep technical mastery.

9 min read
AI CodingSenior
Illustration for Rust Glancer Cuts Language Server Memory Overhead by 100x
Programming/Aug 22, 2026

Rust Glancer Cuts Language Server Memory Overhead by 100x

Reduce IDE overhead. New index structures cut rust glancer lsp ram usage 100x. Run fast language server features on low-spec hardware.

6 min read
RustGlancer
Illustration for 7 Git Mistakes Every Developer Keeps Making
Programming/Jun 28, 2026

7 Git Mistakes Every Developer Keeps Making

After two years of using Git and watching developers struggle with it, these are the mistakes I see most often and how to avoid them.

5 min read
GitVersion Control