Which repository state do Git worktrees share, and which is private to each worktree?
answer
- Repository state versus checkout state
- One object database, one set of branches
- Index and HEAD cannot be shared
- Look inside .git/worktrees/<name>
- Stashes are a ref, so global
basics
~10 sObjects, refs, remotes and repository config are shared by all worktrees. Each worktree keeps its own working directory, index, HEAD, HEAD reflog and in-progress operation state, stored in .git/worktrees/<name> inside the original repository.
solid answer
~40 sThe heavy, repository-wide data lives once: the object database, `refs/heads` and `refs/tags`, remote-tracking refs, hooks and the repository config are shared, so a fetch or a commit in any worktree is immediately visible in all of them. What is per-worktree is the state that describes *this checkout*: the working directory itself, the index, `HEAD`, `ORIG_HEAD`, the HEAD reflog, bisect state and any in-progress merge or rebase. Those live in `.git/worktrees/<name>/`, which the worktree's `.git` file points to via a `gitdir:` line. Stashes are stored under `refs/stash`, so they are shared rather than per-worktree. If you need a config value to differ per worktree, enable `extensions.worktreeConfig` and set it with `git config --worktree`.
code
console · 5 lines$ ls .git/worktrees/review
HEAD ORIG_HEAD commondir gitdir index logs
$ cat .git/worktrees/review/commondir
../..go deeper
Recall the dividing line: the repository's objects and branches are shared, while each worktree has its own files, staging area and current branch.
List both sides precisely and name where the private state lives — .git/worktrees/<name> holding HEAD, the index, the HEAD reflog and any in-progress merge or rebase.
Show the consequences you would warn a team about: branches are exclusive across worktrees, stashes are global, reflog forensics are local to the worktree, and hooks that assume a single checkout path break.
Own the tooling implications — hooks, build scripts and automation must be written against the current working tree rather than a fixed repository path, and per-worktree config is an opt-in extension you decide whether to standardise on.
## Why the split exists A linked worktree is an extra checkout attached to one repository. For that to be useful, anything describing *the project* must be shared — otherwise the worktrees would drift apart and you would effectively have two clones. Anything describing *this particular checkout* must be private — otherwise two directories could not sit on different commits. ## Shared across all worktrees - **The object database** (`objects/`). One copy of every blob, tree, commit and tag. This is what makes adding a worktree cheap and why a commit made in one worktree is instantly readable in another. - **Refs**: `refs/heads/*` (branches), `refs/tags/*`, and remote-tracking refs like `refs/remotes/origin/*`. There is one `main`, not one per worktree. Moving a branch anywhere moves it everywhere. - **Remote configuration** and therefore fetch behaviour: `git fetch` in any worktree updates the remote-tracking branches every worktree reads. - **Repository config** (`.git/config`), including `user.email`, aliases and merge settings. - **Hooks** (`.git/hooks`), so a `pre-commit` hook fires the same way in every worktree. - **Stash entries**, which are a ref (`refs/stash`) and therefore repository-wide. A stash pushed in one worktree is listed in all of them. - **Packed refs, `info/exclude`, and the rest of the repository-level metadata.** ## Private to each worktree Each worktree gets an administrative directory `.git/worktrees/<name>/` inside the original repository, holding: - **`HEAD`** — which branch or commit this checkout is on. This is the whole point: two worktrees on two branches. - **The index** — staged content is per checkout, so staging in one worktree does not affect the other. - **`ORIG_HEAD`** and the **HEAD reflog** (`logs/HEAD`) — the record of where this checkout's HEAD has been. `git reflog` in one worktree does not list the other's movements. - **In-progress operation state** — a running merge, rebase, cherry-pick or revert, plus bisect state, belong to the worktree performing them. You can be mid-rebase in one directory and perfectly clean in another. - **The working directory itself**, and therefore all untracked and ignored files: build outputs, dependency directories, local environment files. The worktree's root contains a `.git` **file** with a single line `gitdir: /path/to/repo/.git/worktrees/<name>`, and that administrative directory contains a `gitdir` file pointing back at the worktree's root plus a `commondir` entry naming the shared repository directory. Because the link is two pointers on disk, moving a worktree with `mv` breaks it — use `git worktree move`, or `git worktree repair` to fix pointers after the fact. ## The one deliberate exception: per-worktree config Sometimes you do want a setting to differ per checkout. Git supports this behind a repository extension: set `extensions.worktreeConfig` to true, then `git config --worktree <key> <value>` writes into a `config.worktree` file for that worktree only, which overrides the shared config. Keys not set there fall back to the shared `.git/config`. This is opt-in precisely because sharing config is the sane default. ## Consequences worth naming in an interview 1. **Branches are a shared, exclusive resource.** Since there is one `refs/heads/x`, Git refuses to check out the same branch in two worktrees, and refuses to delete a branch that some worktree has checked out. 2. **No fetch is needed between worktrees.** Commit in one, and the other can rebase onto it immediately by branch name. 3. **Reflog forensics are local.** If you lost a commit in worktree B, `git reflog` in worktree A will not show the move that lost it — though the object is still in the shared database and reachable by SHA. 4. **Stashes are global, and easy to trip over.** A stash created in one worktree can be popped in another, where its content may not apply cleanly; the entry is not tied to where it came from. 5. **Hooks apply everywhere**, so a hook that assumes one fixed checkout path is a bug waiting to happen. 6. **Ignored files are not shared**, so per-worktree dependency installs and builds are the real setup cost. ## A compact way to say it "Everything that describes the repository is shared — objects, refs, remotes, config, hooks. Everything that describes a checkout is per-worktree — working tree, index, HEAD, its reflog, and any operation in progress — and it lives in `.git/worktrees/<name>`."
- You lost a commit in one worktree. Why might git reflog in another worktree not show it?The HEAD reflog is per-worktree, stored under that worktree's administrative directory, so it records only that checkout's HEAD movements. Run `git reflog` inside the worktree where the loss happened. Branch reflogs under `logs/refs/heads/` are shared, so if the lost work was on a branch its updates are visible everywhere, and the object itself is in the shared database regardless.
- Can two worktrees have different values for a config key?Only if you opt in. Set `extensions.worktreeConfig` to true, then `git config --worktree <key> <value>` writes to a `config.worktree` file scoped to that worktree, which overrides the shared repository config. Without the extension, `.git/config` is shared by every worktree, which is the default and usually what you want.
- If you run git stash in one worktree, can you pop it in another?Yes — stash entries are stored under the shared `refs/stash`, so `git stash list` shows the same entries everywhere. That is easy to trip over: the entry carries no memory of which checkout it came from, so popping it in a worktree on a different branch can conflict or apply changes somewhere you did not intend.
- Do client-side hooks run differently in a linked worktree?No — hooks live in the shared repository directory, so the same scripts run for commits made in any worktree. A hook that hard-codes a path to the main checkout, or assumes only one working directory exists, will misbehave once linked worktrees are in use; write hooks against the current working tree instead.
saying these in an interview costs you the question
- Thinks each worktree keeps its own copy of the branches
- Says a stash created in one worktree is invisible in others
- Assumes reflog output is identical in every worktree
- Believes hooks must be installed separately per worktree
- Claims config can differ per worktree with no extra setup