Part 1: How to Create Git Worktrees and Manage Multiple Branches
Part 1 Git Worktree guide.
Overview
This guide documents how git worktree can make a multi-branch workflow cleaner, safer, and easier to reason about.
The core problem was that I was switching between several active branches inside one local folder. Each branch had different files, different build outputs, different staging needs, and different responsibilities.
That created confusion because the same folder kept changing shape every time I switched branches.
A more reasonable model is to let each major branch have its own working folder.
one Git repository
→ multiple working folders
→ each folder can stand on a different branch
→ less switching issues
→ cleaner testing and deployment workflow
Situation
I was working across several active branches in the private DataInsideData repo:
main
→ stable base branch
feat/add-post
→ posts, how-tos, and fixes content
feat/builder-staging
→ staging deploy workflow and public test site hardening
integration/did-merge
→ combined release candidate branch
staging/builder-showcase-campaign
→ public testing campaign branch
- Switching between these branches in one folder caused extra noise.
- Sometimes generated folder/files stayed behind.
- Sometimes folders/files existed in one branch but not another.
- Sometimes folders/files will gets deleted during branch switching.
It became difficult to know whether I was looking at real branch work, generated output, ignored files, or residue from a previous checkout.
Task
I needed a cleaner way to work across multiple branches without constantly reshaping one folder.
The goal was to create a workflow where each major branch could have its own local folder, while still sharing the same Git repository history.
That way, I could work on posts, staging, and integration without constantly switching one working directory back and forth.
What a Working Tree Means
A working tree is the folder of files you are actively editing.
When I open a repo in VS Code, I am usually looking at one working tree.
Example:
datainsidedata-website/
That folder contains the checked-out files for the branch I am currently standing on.
When I run:
git switch feat/add-post
Git changes that same folder to match the feat/add-post branch.
When I run:
git switch feat/community-projects
Git changes that same folder again to match the feat/community-projects branch.
That works, but it can become messy when branches have very different file structures.
What Git Worktree Adds
git worktree lets one Git repository have multiple working folders.
Instead of switching one folder between branches, I can create separate folders like this:
datainsidedata-website/
→ main or default workspace
datainsidedata-add-post/
→ feat/add-post
datainsidedata-community-projects/
→ feat/community-projects
datainsidedata-builder-staging/
→ feat/builder-staging
datainsidedata-integration/
→ integration/did-merge
Each folder can be opened in a separate VS Code window.
Each folder can stay on its own branch.
This is the big unlock.
Why This Works
Worktrees reduce confusion because the folder no longer has to transform every time I switch branches.
So instead of this:
one folder
→ switch branch
→ folder changes shape
→ generated files remain
→ ignored files remain
→ branch-specific folders appear or disappear
I get this:
one folder per major branch
→ each branch keeps its own working directory
→ less accidental carryover
→ easier local testing
→ easier staging deployments
Important Mental Model
A branch is a line of commits.
A working tree is a folder where one branch is checked out.
A worktree is an additional working folder connected to the same Git repository.
That means it is an official Git-managed checkout.
Copy/Pasting Folders
Copying an entire repo folder manually can create confusion because Git does not know the intent behind the copy.
Manual copying can overwrite files, carry generated folders, duplicate ignored files, or mix work from branches that should stay separate.
git worktree is better because Git manages the relationship between the folders and the branches.
Instead of this for example:
copy entire folder manually
paste into another backup folder
switch branches
copy files back
wonder what changed
Do this:
git worktree add ../datainsidedata-add-post feat/add-post
Now Git creates a real branch-specific workspace.
Check Existing Worktrees
Before creating new worktrees, check what already exists:
git worktree list
Example output:
C:/Users/.../.../datainsidedata-website abc1234 [main]
C:/Users/.../.../datainsidedata-add-post def5678 [feat/add-post]
C:/Users/.../.../datainsidedata-builder-staging 789abcd [feat/builder-staging]
This command shows which folders are connected to which branches.
Create a Worktree for an Existing Local Branch
From the main repo folder, create a separate folder for an existing branch:
git worktree add ../datainsidedata-add-post feat/add-post
Create one for Builder Showcase:
git worktree add ../datainsidedata-community-projects feat/community-projects
Create one for staging:
git worktree add ../datainsidedata-builder-staging feat/builder-staging
Create one for integration:
git worktree add ../datainsidedata-integration integration/did-merge
Each folder can now be opened separately in VS Code.
Open a Worktree in VS Code
Open the new worktree folder:
code ../datainsidedata-add-post
Or:
code ../datainsidedata-builder-staging
This creates a cleaner workflow because each VS Code window is tied to a specific branch folder.
Create a New Branch and Worktree Together
Sometimes the branch does not exist yet.
For example, a staging campaign branch:
git worktree add -b staging/builder-showcase-campaign ../datainsidedata-staging-campaign main
This means:
Create a new branch named staging/builder-showcase-campaign
starting from main
and check it out into ../datainsidedata-staging-campaign
Then push it:
cd ../datainsidedata-staging-campaign
git push -u origin staging/builder-showcase-campaign
Create a Worktree from a Remote Branch
If the branch exists on GitHub but not locally, fetch first:
git fetch origin
Then create a local branch and worktree from the remote branch:
git worktree add -b feat/add-post ../datainsidedata-add-post origin/feat/add-post
This is useful when the remote branch exists but the local branch does not.
Important Rule About Branches and Worktrees
Git usually does not allow the same branch to be checked out in two worktrees at the same time.
That means if feat/add-post is already checked out in:
datainsidedata-add-post/
Git will usually stop me from also checking out feat/add-post in:
datainsidedata-website/
That is a safety feature.
It prevents two folders from editing the same branch at the same time and confusing the branch state.
Suggested Folder Layout
A clean local layout could look something like this:
GitHub_Folders/
datainsidedata-website/
datainsidedata-add-post/
datainsidedata-community-projects/
datainsidedata-builder-staging/
datainsidedata-integration/
datainsidedata-staging-campaign/
Each folder has one job.
datainsidedata-website/
→ main or general admin workspace
datainsidedata-add-post/
→ content work
datainsidedata-community-projects/
→ Builder Showcase feature work
datainsidedata-builder-staging/
→ staging workflow hardening
datainsidedata-integration/
→ combined release candidate testing
datainsidedata-staging-campaign/
→ public testing campaign branch
DataInsideData Branch Map
The branch map can look like this:
feat/add-post
→ write and update content
feat/builder-staging
→ maintain staging deploy workflow
integration/did-merge
→ combine approved work for release testing
main
→ protected production-ready base
Recommended Worktree Setup Commands
From the original private repo folder:
git worktree list
Create content worktree:
git worktree add ../datainsidedata-add-post feat/add-post
Create integration worktree:
git worktree add ../datainsidedata-integration integration/did-merge
Working in a Feature Worktree
Open the feature worktree:
cd ../datainsidedata-community-projects
code .
Work normally:
git status
git add .
git commit -m "Update submit form"
git push
This keeps work in its own folder and branch.
Working in the Content Worktree:
Open the content worktree:
cd ../datainsidedata-add-post
code .
Work normally:
git status
git add .
git commit -m "Add Git branch switching fixes guide"
git push
This keeps posts, how-tos, and fixes separate from other work.
Worktree and Ignored Files
Each worktree has its own working folder.
That means ignored files like .env are not automatically shared across all worktrees.
If a worktree needs local secrets, it may need its own .env.
Example:
datainsidedata-community-projects/.env
datainsidedata-builder-staging/.env
datainsidedata-integration/.env
Because .env is ignored, it should stay out of Git.
A safe pattern is:
.env
→ ignored and manually backed up
.env.example
→ tracked as a template
Worktree and Generated Files
If you’re using Jekyll (Minimal Mistakes) generated files,these are also per worktree.
Each worktree may create its own:
_site/
_site_staging_full/
.jekyll-cache/
.sass-cache/
etc...
That’s okay.
Those should stay ignored and rebuildable.
If a generated folder causes confusion, delete it inside that worktree and rebuild.
Remove-Item -Recurse -Force .\.jekyll-cache
Remove-Item -Recurse -Force .\.folder-name
Then rebuild:
bundle exec jekyll build serve
Worktree and Dependencies
Depending on the project setup, each worktree may also need its own dependency install or bundle path.
For a Jekyll project, if dependencies are managed outside the repo globally, the worktree may already build.
If local vendor folders are used, each worktree may need setup.
Useful check:
bundle install
bundle exec jekyll build
Keep dependency folders ignored:
vendor/
node_modules/
Check out Part 2 here
Data Inside Data™.
Tech Hands, a Science Mind, and a Heart for Community.