# Parallel Worktrees

> Work safely when several people or agent sessions share one repository through git worktrees or parallel checkouts. Use when a repo has sibling worktrees, when changes appear that you did not make, when a stash or branch goes missing, or when setting up a repo for concurrent agent sessions.

- Skill: `chinthakat/parallel-worktrees` (Agent Skill)
- Install (CLI): `npx skillmds@latest add chinthakat/parallel-worktrees`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chinthakat/parallel-worktrees/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: chinthakat (https://skillmd.com/u/chinthakat)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/chinthakat/parallel-worktrees

---


# Parallel worktrees

Git worktrees give each session its own working directory and its own branch.
What they do **not** give each session is its own object store, stash stack,
branch namespace, or anything outside git at all. Almost every surprise comes
from assuming isolation that is not there.

## 1. Know which checkout you are in, before you touch anything

Not the branch — the **directory**. The same branch can be checked out in
several places, and the instructions for "run the deploy from here" usually mean
one specific path.

```bash
git rev-parse --show-toplevel   # which worktree am I in
git worktree list               # what else exists, and on what branch
git status -sb                  # branch, ahead/behind, dirty
```

Do this at the start of a session and again after anything that changes
directory. Paths in project docs are frequently relative to one particular
checkout.

## 2. What is shared, and what is not

| Shared across every worktree | Private to each worktree |
|---|---|
| Objects, refs, remotes | Working tree |
| **The stash stack** | Index |
| Branch names (a branch is checked out in one place at most) | `HEAD` |
| Hooks, most config | Untracked and ignored files |
| Everything outside git: databases, ports, cloud resources, locks | Local env files, build output |

The stash stack is the one that catches people, because nothing about
`git stash` suggests it is global.

## 3. Never use bare `git stash` or `git stash pop`

With concurrent sessions, `stash@{0}` is whatever was pushed most recently by
**anyone**. A bare `pop` can silently take someone else's work and drop it into
your tree, corrupting both sessions in a way that is hard to notice and harder
to undo.

The safe alternative, in order of preference:

1. **A temporary commit.** `git commit -am "wip"` on your own branch, then
   `git reset --soft HEAD~1` later. It is per-worktree, it is recoverable from
   the reflog, and it cannot be taken by anyone else.
2. **A tagged stash, applied by hash:**

```bash
git stash push -u -m "my-unique-tag"
git stash list --format='%H %gs'          # capture YOUR entry's hash
git stash apply <hash>                     # apply, never pop
git stash drop <the stash@{n} that matches your tag now>
```

Re-find the index by tag before dropping. Positions shift as other sessions
push and drop.

## 4. Shared resources outside git need a protocol

Databases, local servers, fixed ports, cloud stacks, deploy pipelines and test
accounts are shared by every session on the machine.

- **Per-worktree ports.** Derive the port from the directory name or keep a
  small map, and start the dev server through a wrapper that applies it. Two
  sessions racing for port 5173 produce an extremely confusing afternoon in
  which one session's changes appear in the other's browser.
- **One designated worktree for deploys and production-data scripts.** Not
  because the code differs, but because the humans need one place to look.
- **A real lock for anything that must not run twice** — a conditional write to
  a small table, a CI concurrency group — with a status command and a TTL.
- **Shared local services started once**, from a documented checkout, not by
  whichever session got there first.

## 5. Branches are a shared namespace

A branch can be checked out in exactly one worktree. `git checkout other-branch`
fails when a sibling holds it, and that error is correct — do not work around it
by force. Create your own branch from the integration branch instead.

Before creating one, check whether the name is taken:

```bash
git worktree list && git branch -a --contains HEAD
```

Never delete a branch you did not create, and never force-push a shared one. If
you rebase a branch another worktree has checked out, that worktree's next
operation will be baffling.

## 6. Merge back often

Long-lived parallel branches are where the real cost shows up. Integrate in both
directions on a regular cadence — daily is not too often when several sessions
are moving:

```bash
git fetch origin
git merge origin/develop        # take everyone else's work
# ... resolve, test ...
git push                        # publish yours
```

Use the repo's sync script if it has one; it usually encodes ordering the raw
commands do not.

## 7. Changes you did not make are not necessarily wrong

When a file looks different from what you expect: check `git log -5 <file>`
before assuming breakage. Another session may have fixed it three minutes ago.

Likewise, do not "tidy" files outside the scope of your task. In a single-session
repo that is a small courtesy; here it produces conflicts in someone else's
active work.

## 8. Untracked config does not propagate

Local env files, credentials and scratch directories are per-worktree and
usually gitignored, so a new worktree starts without them and fails in ways that
look like code problems.

Whatever creates worktrees should copy them, and the README should list what a
fresh worktree needs. When something works in one checkout and not another, this
is the first thing to check.

## Checklist

- [ ] Working directory and branch confirmed at the start of the session
- [ ] No bare `git stash` / `git stash pop`; WIP commit or tagged stash applied by hash
- [ ] Ports, local services and cloud resources deconflicted per worktree
- [ ] Deploys and data scripts run from the designated checkout, behind a lock
- [ ] Own branch created from the integration branch; no force-push on shared branches
- [ ] Merged from the integration branch recently
- [ ] Unexpected changes checked with `git log` before being treated as breakage
- [ ] Untracked local config present in this worktree

