Featured image of post Working on multiple Git branches in parallel

Working on multiple Git branches in parallel

Using Git Worktree to work on multiple branches with one local repository

Follow me

Introduction Link to this section

When working on a project, many times we have to switch to a different branch to help a colleague, fix a bug, or to work on another feature (because of a change in priorities or blocks).

In these situations, we have some options:

  1. Clone again to another folder: This was the option that I used up until some time ago, but if you are working on a big code base, it may take some time to download the remote repository and it will use more space in the disk because you will end up with one copy of the repository for each branch;

  2. Stash or commit changes and checkout the other branch: This is ok, but it takes more steps and doesn’t allow for multiple branches checked out in parallel;

  3. Add a new working tree: This is what I prefer to do because I can have only one local repository shared between the branches.

In this post, I’ll show how to use Git working trees to make those branch switches easier.

Basics of how a Git repository works Link to this section

When we use the git clone command, Git creates two things in the destination: a working tree and a copy of the remote repository (in a .git folder inside the working tree directory).

ℹ️ git clone --bare clones only the repository in the root folder, without the working tree.

Repository Link to this section

The Git repository is a structured directory where Git stores its objects, branches, and other components used to control the versions of our files.

Working tree Link to this section

The working tree is where the actual files we work on are stored. When we use git checkout, Git changes all the files in the working tree to reflect the branch we are working on.

Example Link to this section

git clone https://github.com/dgenezini/MyProject.git MyProject

Working tree and local Git Repository

Within the repository, there are a lot of files and folders, but, for the scope of this post, these are the most important ones:

  • objects = Directory storing blobs (files), trees (directories), and commits;
  • refs = Directory storing pointers to the commits that are the heads of each branch or tag in the repository;
  • HEAD = File pointing to the branch or tag that is checked in in the working tree;
  • index = File used to control what is staged.

Why use Git Worktree? Link to this section

Using the git worktree command, we can create multiple working trees pointing to the same local repository, sharing most of the repository between them.

Instead of a .git directory, the additional working trees have a .git file with a pointer to a working tree folder inside the local repository.

Three working trees and one local Git Repository

In the working tree folder, we have the Git components that are not shared with the other working trees. Note that most of the repository, including the objects folder (files, directories and commits), is shared.

These are the main components in the working tree folders:

  • HEAD = File pointing to the branch that is checked out in the working tree;
  • index = File used to control what is staged in the working tree;
  • commondir = File pointing to the local Git repository.

Using Git Worktree Link to this section

I like to have all the working trees as subfolders, so I start by creating a folder with the name of the repository and cloning the default branch to a folder with the name of the branch (in my case, main).

mkdir MyProject && cd MyProject
git clone https://github.com/dgenezini/MyProject.git main

This is the result I want:

MyProject/   <-- My repo name
└── main          <-- Branch name
    ├── .git      <-- Local repository
    └── README.md

ℹ️ Some people use git clone --bare to pull the repository without a working tree, but the --bare option does not map the branches to their remote origins, so I prefer to clone my default branch (in this example, the main branch), because it is a long living branch, that way I don’t have to manually map the remote origins for every working tree created.

Adding a working tree Link to this section

Inside the main directory, use the git worktree add command:

git worktree add [path] [branch]

Example:

cd main
git worktree add ../featureA featureA

This is will be the result:

MyProject/   <-- My repo name
├── featureA      <-- Branch name
│   ├── .git      <-- File pointing to ../main/.git
│   └── README.md
└── main          <-- Branch name
    ├── .git      <-- Git local repository
    └── README.md

ℹ️ You can use the git worktree add and other Git commands inside any working tree directory.

⚠️ If you are using windows, change the slash on the path from ../featureA to ..\featureA.

Changing to a working tree Link to this section

Just change the directory you are working on:

cd ../featureA

Removing a working tree Link to this section

Inside the main directory, use the git worktree remove command:

git worktree remove [branch]

Example:

git worktree remove featureA

or just delete the working tree folder (featureA in this example), then use git worktree prune to clean the invalid working trees.

Git Worktrees extension for Visual Studio Code Link to this section

Git Worktrees is a free extension for Visual Studio Code that helps us work with Git working trees.

Adding a working tree Link to this section

Open the Command Palette (Ctrl+Shift+P) and type worktree add

Adding a working tree with Git Worktrees extension for VS Code

Changing to a working tree Link to this section

Open the Command Palette (Ctrl+Shift+P), search for worktree list and select Git Worktree: List.

Changing to a working tree with Git Worktrees extension for VS Code

Select the branch you want to work on and VS Code will open another window in that working tree.

Selecting the branch

Removing a working tree Link to this section

Open the Command Palette (Ctrl+Shift+P), search for worktree remove and select Git Worktree: Remove.

Removing a working tree with Git Worktrees extension for VS Code

Select the branch you want to remove.

Selecting the branch

⚠️ You can’t remove the working tree you have currently open in VS Code.

Changing the working tree from Visual Studio 2022 Link to this section

Visual Studio is my favorite IDE for working with .NET, so it is important that I can change easily between working trees from within it.

Once you open the project from the working tree for the first time, Visual Studio will keep track of the working tree as a repository in the status bar. Just change it from there and it will load the project.

Changing to a working tree in Visual Studio 2022

💬 Like or have something to add? Leave a comment below.
Ko-fi
GitHub Sponsor
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy