async-doc-hook-autodocs-worktree-locks-branch-checkout · v1.0.0 · 2026-07-08 · sha256 32d38a94bd3aeb43

async-doc-hook-autodocs-worktree-locks-branch-checkout v1.0.0A

Immutable. This exact content is served forever at /api/v1/blob/32d38a94bd3aeb43.

---
name: async-doc-hook-autodocs-worktree-locks-branch-checkout
description: |
  Fix for `git checkout <branch>` failing with `fatal: '<branch>' is already used by
  worktree at '.../autodocs-<name>'` (or a subagent reviewing a PR reports a path like
  `.../worktrees/autodocs-<topic>/...`). Use when: (1) right after a commit whose hook
  printed `[post-commit] Python files changed — running doc update in background...`, a
  later branch switch is blocked; (2) you can't check out the branch you just committed to
  because "another worktree" holds it; (3) a review/subagent cites a file path under an
  `autodocs-*` worktree you never created. Root cause: the async post-commit doc-update hook
  spawns its OWN git worktree on the active branch (git forbids a branch being checked out in
  two worktrees). Fix: `git worktree remove --force` the autodocs worktree (after confirming
  it committed nothing), then checkout proceeds. Distinct from the index.lock variant — see
  worktree-index-corrupt-async-post-commit-hook.
author: Claude Code
version: 1.0.0
date: 2026-06-01
disable-model-invocation: true
---

# Async doc-update hook spawns an autodocs worktree that locks your branch

## Problem
This repo's async post-commit hook ("running doc update in background") materializes its own
git worktree (e.g. `.claude/worktrees/autodocs-<topic>`) and checks out the branch you just
committed to. Git only allows a branch to be checked out in ONE worktree, so a subsequent
`git checkout <that-branch>` in your main worktree fails:

```
fatal: '<branch>' is already used by worktree at
'/…/.claude/worktrees/autodocs-<topic>'
```

It also surfaces indirectly: a code-review subagent you pointed at the PR may report file
paths under `.../worktrees/autodocs-<topic>/...` — that's the hook's worktree, not yours.

## Context / Trigger conditions
- You committed on a feature branch; the commit output included
  `[post-commit] Python files changed — running doc update in background...`.
- You then try to switch back to that branch (e.g. to apply a review fix) and git refuses.
- A subagent's review cites an `autodocs-*` path.
- Sibling symptom (different fix): the same hook also leaves `index.lock` behind →
  `Unable to create '.git/worktrees/<name>/index.lock'` → that's `rm -f` (see See also).

## Solution
1. **Confirm the hook committed nothing to your branch** (it usually only reads/regenerates
   docs and leaves them uncommitted):
   ```bash
   git rev-parse <branch>            # local tip
   git rev-parse origin/<branch>     # remote tip (if pushed)
   git log --oneline <your-sha>..<branch>   # empty = no extra commits
   ```
   If local == remote == your commit and the range is empty, the autodocs worktree added
   nothing — safe to remove.
2. **Force-remove the autodocs worktree** to free the branch:
   ```bash
   git worktree remove --force .claude/worktrees/autodocs-<topic>
   git worktree list | grep autodocs   # should be gone
   ```
3. **Now checkout works.** Clear any leftover lock first if present:
   ```bash
   rm -f .git/worktrees/<your-worktree>/index.lock
   git checkout <branch>
   ```

## Verification
- `git worktree list` no longer shows the `autodocs-*` entry.
- `git checkout <branch>` succeeds; `git rev-parse --short HEAD` == your commit.

## Example (S227)
Committed P1 (`23f36f6d`) on `s227-auc-floor-recalibration`, switched to a sibling branch to
build P2, then needed to return to apply a reviewer's DRY fix. `git checkout
s227-auc-floor-recalibration` →
`fatal: '…' is already used by worktree at '…/autodocs-s227-recalib'`. The P1 review subagent
had also been reporting `…/worktrees/autodocs-s227-recalib/…` paths. Confirmed local ==
origin == `23f36f6d` (hook committed nothing), `git worktree remove --force
.claude/worktrees/autodocs-s227-recalib`, then checkout succeeded.

## Notes
- The autodocs worktree is hook scratch — force-removing it is safe once you've confirmed it
  holds no unique commits. If it DID commit (rare), cherry-pick first.
- Don't `git branch -D` the branch to "unstick" it — that destroys your work; remove the
  worktree instead.
- Same underlying async hook as the `index.lock` failure, but a different symptom and fix.

## References
- See also: `worktree-index-corrupt-async-post-commit-hook` (index.lock variant of the same
  hook), `git-rebase-stalls-async-post-commit-hook`, `git-amend-hits-async-post-commit-hook-commit`,
  `concurrent-session-checkout-clobbers-shared-worktree`, `gh-pr-merge-worktree-checkout-trap`.