Skip to content
Back to skills

Concurrent Session Checkout Clobbers Shared Worktree

ASecurity

A second Claude Code session (or agent/person) sharing the same working directory runs `git checkout`/`git switch`, flipping the branch for the whole working tree underneath your session and clobbering your uncommitted work. Use when: (1) a file you just edited has silently reverted — often with a "file was modified, either by the user or by a linter" system reminder, (2) `git branch --show-current` shows a branch you didn't switch to, (3) `git reflog` shows a `checkout: moving from X to Y` y...

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 5, 2026
ai-agentspythongoshellbashgit

Works with

  • claude code

Security analysis

A100/100

Scanned September 22, 2026

npx -y skills add wan-huiyan/agent-traffic-control --skill concurrent-session-checkout-clobbers-shared-worktree --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Concurrent Session Checkout Clobbers Shared Worktree?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Concurrent Session Checkout Clobbers Shared Worktree
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wan-huiyan-concurrent-session-checkout-clobbers-shared-worktr/badge)](https://www.skillsdirectory.com/skills/wan-huiyan-concurrent-session-checkout-clobbers-shared-worktr)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: concurrent-session-checkout-clobbers-shared-worktree
description: |
  A second Claude Code session (or agent/person) sharing the same working
  directory runs `git checkout`/`git switch`, flipping the branch for the whole
  working tree underneath your session and clobbering your uncommitted work.
  Use when: (1) a file you just edited has silently reverted — often with a
  "file was modified, either by the user or by a linter" system reminder,
  (2) `git branch --show-current` shows a branch you didn't switch to,
  (3) `git reflog` shows a `checkout: moving from X to Y` you never ran,
  (4) unfamiliar files/changes appear in `git status`. Covers detecting the
  collision and recovering via an isolated git worktree. Every trigger above is
  a symptom, so this skill fires only once damage exists; the pre-dispatch check
  that prevents the fan-out case is a separate skill,
  `pre-dispatch-agent-isolation-parameter-not-prompt`.
author: Claude Code
version: 1.2.0
date: 2026-06-23
disable-model-invocation: true
---

# Concurrent session's `git checkout` clobbers your shared working directory

## Problem

Two Claude Code sessions (or any two agents/people) operate in the **same**
working directory on the same clone. `git checkout` / `git switch` changes
`HEAD` for the *entire working tree* — it is not per-session. When session B
switches branches, session A's tree changes underneath it:

- Uncommitted edits to tracked files may be carried across, reverted, or left
  in a confusing half-state.
- Untracked files (new files you created) stay on disk but risk being swept
  into session B's next `git add -A`.
- Edits get silently lost — e.g. a config field you added disappears.

It is invisible until something breaks: a function you wrote is "gone", a test
errors on a symbol you defined, or a harness emits *"file was modified, either
by the user or by a linter"* for a file you didn't expect to change.

## Context / Trigger Conditions

- A file you edited reverted to an older version with no action from you.
- `git branch --show-current` is not the branch you were working on.
- `git status` lists changes or untracked files you don't recognize.
- **Decisive:** `git reflog` shows `checkout: moving from <yours> to <other>`
  that you never performed.

## Solution

Do **not** keep fighting inside the shared directory — you will collide again.
Isolate into a git worktree.

1. **Confirm the collision** — `git reflog -5` reveals the foreign checkout.
   `git log <your-branch> --oneline` confirms your committed work is still safe
   on its branch (commits survive a checkout; only uncommitted work is at risk).
2. **Create a worktree for your existing branch** (not a new branch):
   ```bash
   git worktree add /path/outside/repo/my-worktree <your-branch>
   ```
   Place it *outside* the repo (a sibling dir) to avoid `.gitignore` edits that
   would themselves collide.
3. **Migrate uncommitted work into the worktree:**
   - Copy untracked files (`cp` the new files you created).
   - Re-apply tracked-file edits in the worktree (apply them fresh; the
     worktree has the clean branch tip).
   - Re-apply any edit that was *clobbered* — recover it from conversation
     context.
4. **Clean your pollution out of the shared dir** so the other session gets it
   back as expected: `git checkout <files-you-modified>` and `rm` your untracked
   files (you copied them already).
5. **Switch your session into the worktree** and continue there.
6. **Commit early and often** to your feature branch — committed work cannot be
   clobbered by a foreign checkout.

## Verification

- `git worktree list` shows your isolated worktree on your branch.
- Your work (files + edits) is present in the worktree; tests pass there.
- The shared directory's `git status` shows only the *other* session's files.

## Synthetic example

Session A is on `feature/config-validation` with an uncommitted `app/config.py` edit.
The parallel session runs `git checkout feature/settings-page` in the shared `repo/`.
Session A's `app/config.py` edit vanishes; `git reflog` shows
`checkout: moving from feature/config-validation to feature/settings-page`. Recovery:
`git worktree add ../config-worktree feature/config-validation`, copy the untracked new
files in, re-apply the lost `config.py` edit, `git checkout app/main.py` + `rm`
the strays in `repo/`, then `EnterWorktree` and carry on — committing each task.

## If YOU dispatched the agents: the prevention lives in a different skill

Everything on this page is recovery, and every trigger above is a symptom — so if you are
the one who fanned agents out believing they were already isolated, nothing here will
prompt you to look until the damage exists.

**Prose in a dispatch prompt is not configuration.** The isolation comes from the dispatch
tool's `isolation: "worktree"` parameter and from nothing else; a prompt opening *"You are
in your OWN isolated git worktree"* creates no worktree. The pre-dispatch check for that —
read the call back, and make each agent print `git rev-parse --show-toplevel` and
`git branch --show-current` as its first bash call — is
[`pre-dispatch-agent-isolation-parameter-not-prompt`](https://github.com/wan-huiyan/agent-traffic-control/blob/main/plugins/agent-traffic-control/skills/pre-dispatch-agent-isolation-parameter-not-prompt/SKILL.md).
It carries the worked example and the tell; it is not repeated here.

## Notes

### Variant — a stale `index.lock` blocks BOTH concurrent sessions (v1.1.0)
Symptom: `git commit`/`git add` fails with `Unable to create '.git/.../index.lock': File exists.
Another git process seems to be running`. In a shared worktree this often is **not** an active git
op — it's an **orphaned lock** from an earlier commit that was killed (e.g. a session interrupted
mid-commit), and it blocks *every* session sharing the directory, including a parallel one that's
sitting in a retry loop waiting for the lock to clear (so nobody makes progress). Diagnose stale vs
active before removing:
- **Lock age**: `python3 -c "import os,time;p='.git/worktrees/<wt>/index.lock';print(round(time.time()-os.path.getmtime(p)))"` — a multi-minute-old, 0-byte lock is almost certainly orphaned.
- **No active git op**: `ps aux | grep -E '[g]it (commit|add|push|merge|rebase)'` returns nothing (a sibling's *polling shell loop* may appear, but that's not a git op holding the lock — its own args often reveal it's waiting on the same lock).
Then `rm -f` the lock and commit **specific paths** with a short retry guard (the sibling may grab
the freed lock first; loop 3–5× with a `sleep 2`). Removing it unblocks *both* sessions. Only remove
after both checks pass — deleting a lock held by a live git process corrupts the index.

- Prevention: when starting isolated feature work, create a worktree *first*
  (the `using-git-worktrees` skill). Shared-directory work is only safe for a
  single session.
- A native `EnterWorktree` tool can enter an already-created worktree by `path`.
- Nothing is permanently lost even if the other session commits your strays —
  file *content* survives; you can recover it. But it is messy; isolate early.

## References

- `using-git-worktrees` — create an isolated workspace up front.
- `git reflog` is the source of truth for "who switched the branch."

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.