Skip to content

Making the Most of Git Worktrees and Dev Containers

When several AI agents work on the same project, the code changes are not the only thing that can collide. One agent may need Python 3.10, another may need Python 3.12, and a third may be testing a dependency upgrade. If they all share the same environment, the work quickly becomes harder to reason about.

Git worktrees and Dev Containers solve different parts of that problem. Worktrees separate the code. Dev Containers separate the runtime. Used together, they make parallel work much easier to manage. There is one catch, though: a worktree can stop behaving like a normal Git repository once it is opened inside a container. I built a template repository to solve that problem and make it easy to set up the pattern in your own projects. Know more about in the next sections.

The Parallel AI Development Problem

Parallel development sounds simple on paper: create a few branches, let each agent work on one branch, and compare the results.

The code may be isolated, but the environment often is not. One agent installs Python 3.10 dependencies, another expects Python 3.12, and a third updates a package that affects the others. At that point, the environment becomes the main source of friction.

The important distinction is that branch isolation does not solve environment isolation. For parallel work to stay manageable, you need both:

  1. Branch isolation for separate code changes
  2. Environment isolation for separate runtime setups

Enter: Git Worktrees + Dev Containers

This is where the two pieces fit together.

Git worktrees let you check out multiple branches at the same time in separate folders. For example:

Bash
git worktree add ../agent-a-python-310 -b agent-a-python-310
git worktree add ../agent-b-python-312 -b agent-b-python-312
git worktree add ../agent-c-upgrade -b agent-c-upgrade

That gives you three folders and three branches from the same repository.

Dev Containers give each folder its own containerized environment. Each branch can have its own:

  • Python/Node/Ruby version
  • Dependency tree
  • Tooling stack
  • Isolated filesystem

Open agent-a-python-310/ in VS Code and connect it to a Python 3.10 container. Open agent-b-python-312/ in VS Code and connect it to a Python 3.12 container. Open agent-c-upgrade/ in VS Code and connect it to the upgraded dependencies container.

At that point, each agent can work with a different branch and a different runtime.

That sounds like the whole solution, but there is one more detail to handle.

The Technical Landmine

If you open a worktree in a Dev Container without adjusting the mount, Git can stop working inside the container. The symptom looks like this:

Text Only
$ git status
fatal: not a git repository (or any of the parent directories): .git

The worktree is still valid on the host, but the container cannot see the repository metadata it needs.

The reason is that a linked worktree does not contain a full .git directory. Instead, it contains a .git file that points back to the main repository's metadata:

Text Only
gitdir: /Users/you/projects/main-repo/.git/worktrees/agent-a

When VS Code opens a Dev Container, it usually mounts only the folder you opened, such as agent-a-python-310/. If the .git pointer refers to a path that is not visible inside the container, Git cannot find the repository metadata.

The result is that Git commands fail inside the container, even though the worktree is fine on the host.

The Fix: It's All About the Mount

The fix is to mount the parent directory so the .git pointer remains valid inside the container.

Start with a shared parent directory:

1. Keep the worktrees under a shared parent:

Text Only
my-project-workspace/          ← Shared parent
├── main-repo/                 ← Main repository (contains .git/)
│   └── .devcontainer/
├── agent-a-python-310/        ← Worktree 1
│   └── .devcontainer/
├── agent-b-python-312/        ← Worktree 2
│   └── .devcontainer/
└── agent-c-upgrade/           ← Worktree 3
    └── .devcontainer/

2. Configure .devcontainer/devcontainer.json to mount that parent directory:

JSON
{
    "name": "agent-container",
    "image": "mcr.microsoft.com/devcontainers/python:3.12",
    "mounts": [
        "source=${localWorkspaceFolder}/..,target=${localWorkspaceFolder}/..,type=bind,consistency=cached"
    ],
    "postCreateCommand": "git config --global --add safe.directory \"${containerWorkspaceFolder}\""
}

What this does:

  • The mount: Makes the parent directory visible inside the container so the linked worktree can still reach its Git metadata
  • The postCreateCommand: Marks the worktree path as a safe Git directory inside the container

3. Open each worktree in VS Code and reopen it in the container:

After that, opening agent-a-python-310/ in a container should work as expected:

  • The parent directory is available inside the container
  • The .git pointer resolves correctly
  • Git commands work normally
  • The agent can commit, push, and manage branches

Security note: Because the parent directory is mounted, all sibling worktrees are visible to the container. It is best to use a dedicated parent directory that contains only the repository and its worktrees.

What This Unlocks

Once this is in place, parallel work becomes much easier to manage:

Scenario 1: Python Version Compatibility Testing

  • Create two worktrees with different .devcontainer base images
  • Have one agent test Python 3.10 and another test Python 3.12
  • Run both at the same time without the environments interfering
  • Compare the results and merge the better option

Scenario 2: Dependency Upgrade Isolation

  • Keep the main branch on stable dependencies
  • Put the upgrade in a separate branch
  • Test it without affecting the stable environment
  • Roll back easily if the upgrade causes problems

Scenario 3: Multiple Agents, Multiple Approaches

  • Agent A tries a safe refactor
  • Agent B attempts a larger rewrite
  • Agent C implements a minimal fix
  • Review the approaches side by side

The Results

This pattern tends to produce a few practical benefits:

  • Faster iteration: Agents can work in parallel instead of waiting on each other
  • Fewer environment conflicts: Each branch gets its own runtime
  • Better focus: Agents spend less time dealing with setup issues
  • Easy cleanup: Remove the worktree, remove the container, and start fresh
  • Safer experimentation: Try more than one approach without touching the stable setup

Try It Yourself

The full setup is available as a template repository:

github.com/kanad13/git-worktrees-and-vscode-devcontainers

What you get:

  • Pre-configured .devcontainer/ folder (copy into your repo)
  • Complete setup guide
  • Detailed concepts documentation
  • Smoke test script to verify everything works

The Bigger Picture

This is not just useful for AI agents. It helps in any workflow where you need:

  • Multiple branches active simultaneously
  • Different runtime environments per branch
  • Working Git commands in each environment
  • Fast setup and teardown

It applies whether you are:

  • Testing across language versions
  • Running experiments side-by-side
  • Onboarding agents or people to isolated tasks
  • Comparing architectural approaches

In short, it gives you a practical foundation for parallel development.