Hi,
refs/stash is shared by the main checkout and every linked worktree, so two worktrees push onto and pop from the same stack. With git 2.52.0:
git init wt-a && cd wt-a
git commit --allow-empty -m base
git worktree add ../wt-b -b b echo A >file-a && git add file-a
git stash push -m "worktree A: half-finished refactor" cd ../wt-b
echo B >file-b && git add file-b
git stash push -m "worktree B: unrelated fix"
git stash pop # worktree B's own entry, as expected
git stash pop # worktree A's entry, applied hereAfter the second pop, wt-b holds both file-a and file-b, and wt-a has an empty stash and a clean tree. Nothing warned about it, and the entry is gone from the stack, so wt-a has no way to find out where its changes went.
This is documented behavior: git-worktree(1) lists refs/bisect, refs/worktree and refs/rewritten as the per-worktree exceptions, and refs/stash is not among them. For a human who drives one worktree at a time it is mostly harmless, and sharing is occasionally useful - stash in one worktree, apply in another, as a way to move work across checkouts.
What changed is who runs these commands. Running one coding agent per worktree, against one repository, has become a common setup, and the agents stash and pop on their own schedule. The failure above then turns into silent data movement between unrelated sessions. The same report has already been filed against at least two such tools:
https://github.com/github/copilot-cli/issues/1725
https://github.com/stablyai/orca/issues/13695I would like to propose a configuration knob rather than a new concept, because most of the machinery is already in the tree:
- refs/worktree/* is per-worktree, so a private stack has somewhere
to live;
- `git stash export --to-ref` and `git stash import` already read and
write a stash stack under an arbitrary ref;
- extensions.worktreeConfig and `git config --worktree` already give
a worktree its own configuration.The missing piece is telling stash itself which ref to use. Say stash.ref, defaulting to refs/stash, honored by push, save, list, show, pop, apply, drop, branch and clear. A worktree that wants isolation then asks for it once:
git config extensions.worktreeConfig true
git config --worktree stash.ref refs/worktree/stashNothing changes for anyone who does not set it, and the tools that manage worktrees for agents can set it when they create a worktree.
Alternatives I considered and rejected:
- Making the stash per-worktree unconditionally. It breaks the
stash-here-apply-there workflow, and it moves existing entries out
from under scripts. If that is the destination, it belongs in
Documentation/BreakingChanges.adoc for Git 3.0, with a warning
released first - but it does not have to block a knob today. - Named stashes. A name that survives a push by another process is
what a ref already is, so this would grow a second naming scheme
over the one branches and tags already use, plus commands to list
and delete those names. - Leaving it to tooling. It works - `git stash create` writes a
stash commit without touching any ref, so a wrapper can store it
under refs/worktree/<name> and apply it later - but every tool
reimplements it, and the failure mode for anyone who does not is
silent.Points I am not sure about, and where I would like guidance before writing a patch:
- Whether stash.ref is the right name, and whether it should be
restricted to refs/ (rejecting a value that is not a ref name). - Whether `git stash list` should be able to show the other stacks -
a worktree's entries becoming invisible to the main checkout is the
cost of the knob, and `git stash list --all` over
worktrees/*/refs/worktree/stash might be a reasonable answer. - Reachability. fsck and reflog expiry learned to iterate
per-worktree refs, and I would like a second opinion on whether
stash entries under refs/worktree/* are safe from gc in the same
way refs/stash entries are.If the direction sounds reasonable, I am happy to write the patch.
Thanks, Vladimir Sitnikov