This folder contains a VS Code Dev Container configuration for linked Git worktrees.
For more context on why this is useful and how it works, see the main readme.md and concepts.md.
Follow the setup instructions below to create linked worktrees and open them in containers without breaking Git commands.
You need:
- Git
- Docker
- VS Code
- the Dev Containers extension
This setup officially targets:
- macOS
- Linux
- Windows via WSL
Assuming you have an existing repository, say my-project, then create a new folder named something like my-project-worktrees and move the repository into it.
Example:
my-project-worktrees/
my-project/ ← main repository
The shared parent directory is important because it allows the container to see the main repository's Git metadata from each linked worktree, which is how it can run Git commands without breaking.
That dedicated parent becomes both:
- the extra bind-mount boundary used by the container
- the Git trust boundary for
parent/*
Copy the .devcontainer/ folder from this repository into the root of your main repository, which is now my-project/ in the example layout.
After copying it, your layout should look like this:
my-project-worktrees/
my-project/
.devcontainer/
Because each linked worktree is its own checkout of the repository, each worktree will also contain the same .devcontainer/ folder.
Now create linked worktrees using plain Git commands. The worktree command can create new branches and check them out simultaneously.
For new branches (creates the branch and worktree in one step):
cd my-project-worktrees/my-project/
git worktree add ../branch-1 -b branch-1 main
git worktree add ../branch-2 -b branch-2 mainIf a branch already exists locally, omit the -b flag:
git worktree add ../branch-1 branch-1Your layout will then look like this:
my-project-worktrees/
my-project/
.devcontainer/
branch-1/
branch-2/
Open each folder separately in different VS Code windows:
my-project/branch-1/branch-2/
VS Code should detect .devcontainer/ and offer to reopen the folder in a container.
Each worktree can then run in its own containerized environment.
You have 3 ways to verify that the setup is working:
- Inside the VS Code UI
- With the Dev Container CLI
- With the repository's smoke test script
Open VS Code and open one of the worktree folders, for example branch-1/.
When you open the terminal in VS Code, you should be inside the container environment. Run:
git status
git log --oneline -5
cat .gitYou want to see all of the following:
git statusworks without a repository errorgit logworks normally.gitcontains a pointer back to Git admin data owned by the main repository
Instead of verifying inside the VS Code UI, you can do the same check with the Dev Container CLI:
devcontainer up --workspace-folder /path/to/branch-1
devcontainer exec --workspace-folder /path/to/branch-1 git status
devcontainer exec --workspace-folder /path/to/branch-1 git log --oneline -5
devcontainer exec --workspace-folder /path/to/branch-1 sh -lc 'cat .git && printf "\n---\n" && git config --global --get-all safe.directory'That lets you confirm both parts of the fix:
- the linked worktree's
.gitpointer still resolves inside the container safe.directorytrusts the sibling set under the shared parent
If you want this repository itself to run that verification automatically, use the smoke test script from the repository root:
bash .devcontainer/smoke-test.shThe smoke test will:
- create a temporary Git repository
- copy in this repo's
.devcontainer/folder - create a linked worktree
- start the linked worktree in a Dev Container
- verify that Git works inside the container
- verify that
.gitstill points to the shared Git metadata - verify that
safe.directorywas configured for both/workspaces/*and the mirrored host parent path
By default it cleans up the temporary directory and container after a successful run. If the smoke test fails, it keeps the temporary workspace so you can inspect what went wrong. If you want to keep the artifacts even after a successful run, use:
KEEP_SMOKE_TEST_ARTIFACTS=1 bash .devcontainer/smoke-test.shCreate worktrees for testing Python version compatibility.
The important detail is that this template reads the image field directly from .devcontainer/devcontainer.json. If you want different branches to use different base images, edit that field in each branch's copy of devcontainer.json.
# Create a test branch worktree
cd my-project-worktrees/my-project
git worktree add ../python-3.10-test -b python-3.10-testThen update .devcontainer/devcontainer.json in each worktree, for example:
// my-project/.devcontainer/devcontainer.json
"image": "mcr.microsoft.com/devcontainers/python:3.12"
// python-3.10-test/.devcontainer/devcontainer.json
"image": "mcr.microsoft.com/devcontainers/python:3.10"Each worktree can customize its own devcontainer.json independently.
Test dependency upgrades in isolated branches:
# Branch A: stable dependencies
git worktree add ../stable-deps -b stable-deps
# Branch B: upgraded dependencies
git worktree add ../upgrade-test -b upgrade-test
cd ../upgrade-test
# Modify requirements.txt or package.json for testingEach container will have its own isolated environment, preventing conflicts.