Skip to main content

Git worktrees–A first step towards a multi-agent development workflow

As AI coding assistants become more sophisticated, we're approaching a future where multiple agents might work on different parts of your codebase simultaneously. But there's a challenge: how do you let multiple processes work on the same repository without constantly stepping on each other's toes?

One solution is to have agents work on dedicated machines like GitHub Copilot Agent does in a GitHub Codespace. But what if you want to have multiple agents working on your local machine?

Enter git worktrees – a powerful Git feature that's been hiding in plain sight since 2015, and the perfect foundation for multi-agent development workflows.

What are Git worktrees?

Git worktrees allow you to check out multiple branches from the same repository simultaneously, each in its own directory. Think of it as having multiple working directories all sharing the same Git history, but each can be on a different branch.

Here's the key insight: while the working directories are separate, they all share the same .git directory.

This means:

  • No duplication of Git history
  • Minimal disk space overhead
  • Lightning-fast branch creation
  • Perfect isolation between workspaces

Enter multi-agent development

When you have multiple AI agents working on your codebase:

  • Agent A might be refactoring the authentication system
  • Agent B could be writing tests for the API layer
  • Agent C might be experimenting with a new UI component

With worktrees, each agent gets its own isolated workspace. They can run builds, execute tests, and make changes without interfering with each other – all while sharing the same underlying repository.

Important is to use a good directory and naming structure. Here's one way to do it:

~/projects/
├── my-app/                 # Main worktree (main branch)
├── my-app-agent-1/         # Agent 1's workspace
├── my-app-agent-2/         # Agent 2's workspace
└── my-app-hotfix/          # Quick hotfix workspace

Getting started

Let's say you're working on the main branch and need a separate workspace:

# Create a new worktree for a feature branch
git worktree add ../my-repo-feature feature/new-auth

# Create a worktree with a new branch
git worktree add -b feature/api-refactor ../my-repo-api

This creates a new directory at ../my-repo-feature with the feature/new-auth branch checked out.

You can see the list of created worktrees:

git worktree list

Output:

/home/user/projects/my-repo         abc123d [main]
/home/user/projects/my-repo-feature def456e [feature/new-auth]
/home/user/projects/my-repo-api     ghi789f [feature/api-refactor]

When you're done with a worktree:

# Remove the worktree
git worktree remove ../my-repo-feature

# Or if you've already deleted the directory
git worktree prune

Using worktrees in VS Code

VS Code recently added support for git worktrees., You can create a new worktree directly from the UI:

And of course, also delete it, when you no longer need it:

 

Remark: Although Visual Studio does not have native support for Git worktrees, you can use this feature through the Git WorkTree extension available on the Visual Studio Marketplace.

More information

Git - git-worktree Documentation

Git WorkTree - Visual Studio Marketplace

Popular posts from this blog

Podman– Command execution failed with exit code 125

After updating WSL on one of the developer machines, Podman failed to work. When we took a look through Podman Desktop, we noticed that Podman had stopped running and returned the following error message: Error: Command execution failed with exit code 125 Here are the steps we tried to fix the issue: We started by running podman info to get some extra details on what could be wrong: >podman info OS: windows/amd64 provider: wsl version: 5.3.1 Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM Error: unable to connect to Podman socket: failed to connect: dial tcp 127.0.0.1:2655: connectex: No connection could be made because the target machine actively refused it. That makes sense as the podman VM was not running. Let’s check the VM: >podman machine list NAME         ...

Cache stampede: when our cache turned against us

While investigating some performance issues, we ran into an ASP.NET Core API that cached a fairly expensive aggregation query for 60 seconds. Under normal load, that was fine: one request rebuilds the cache, everyone else reads from it. Under peak load, dozens of requests would arrive in that same expiry window, all see a cache miss, and all fire the same expensive query in parallel. The database didn't like that. That was the moment when our caching layer stopped helping and started hurting. A burst of requests comes in at the same time, all miss the cache, and all go hammer the database or the downstream API at once. That's a cache stampede . The cache was supposed to protect our backend, and for a few hundred milliseconds it did the opposite. Why this happens IMemoryCache.GetOrCreate (and its async sibling) looks like it protects you, but it doesn't add any locking on its own. Look at the naive version: public async Task<Report> GetReportAsync(string key) ...

A complex system designed from scratch never works

A few years ago, I worked as an architect on a big mainframe rewrite. I still count it as one of my failures. Not because the technology was wrong, but because I couldn't convince the management team to simplify the approach. Years later, the organization is still struggling to get the new system up and running. I left the project at the time, because I couldn't put my name behind an approach that would take very long and cost a lot of money without a working system to show for it along the way. Gall’s Law That memory keeps coming back to me, because it's a textbook case of Gall's Law playing out in real life. Gall's Law , from John Gall's Systemantics , states it plainly: A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works, and it cannot be patched to make it work. You have to start over with a simple system that works. What does that mean in practice,...