Affected Packages
@changesets/cli
@changesets/git
Summary
When a pre-push hook runs changeset status --since=<ref> from inside a git worktree, the command spuriously fails with:
🦋 error Some packages have been changed but no changesets were found. Run `changeset add` to resolve this error.
🦋 error If this change doesn't need a release, run `changeset add --empty`.
The same command run directly from a shell in the same directory succeeds and reports the expected packages-to-be-bumped. Root cause: git invokes hooks with GIT_DIR set to the worktree-specific git directory (e.g., <repo>/.git/worktrees/<name>) but does not set GIT_WORK_TREE. Changesets CLI's internal git diff / git ls-tree invocations then resolve the working tree incorrectly and return an empty list of changed changeset files, even though the .changeset/*.md file is present in HEAD.
Repro (minimal, env-var only)
In any repo with Changesets and an existing changeset file on a feature branch:
# Works
pnpm changeset status --since=origin/main
# 🦋 info Packages to be bumped at minor:
# 🦋 - @your/pkg
# Fails (mimics what git sets for hook processes inside a worktree)
GIT_DIR=$(git rev-parse --git-dir) pnpm changeset status --since=origin/main
# 🦋 error Some packages have been changed but no changesets were found.
# Works again (restores the missing half of the env pair)
GIT_DIR=$(git rev-parse --git-dir) GIT_WORK_TREE=$(pwd) pnpm changeset status --since=origin/main
# 🦋 info Packages to be bumped at minor:
# 🦋 - @your/pkg
The minimal hook reproduction adds the wrinkle that git push sets GIT_DIR automatically inside a worktree, so users hit this without any explicit env setup — only on their non-main worktree pushes, and only when --since=<ref> is used.
Where I traced it
getChangedChangesetFilesSinceRef in @changesets/git spawns:
git diff --name-only --diff-filter=d --no-relative <divergedAt>
With GIT_DIR inherited and GIT_WORK_TREE unset, this returns an empty/incorrect file list — git can't resolve the work tree because GIT_DIR overrides cwd-based discovery but the partner var isn't there to anchor it.
filterChangesetsSinceRef in @changesets/read then filters out every present .changeset/*.md (because none match the now-empty "changed files since ref" set), so changesets.length === 0 and the status command reports "no changesets were found" despite the file being on disk and committed in HEAD.
Suggested fix
In @changesets/git, either:
- Unset
GIT_DIR in the child git spawns (let git auto-discover from the passed cwd), or
- Set
GIT_WORK_TREE alongside the inherited GIT_DIR when calling spawn("git", ...).
Option 1 is the more conservative fix and aligns with the existing cwd parameter already being passed to every spawn call. The current code implicitly assumes git will use cwd for working-tree resolution, which holds only when GIT_DIR is also unset or paired with GIT_WORK_TREE.
Environment
@changesets/cli 2.31.0 / @changesets/git 3.0.4
- pnpm 11.1.3, Node 24, macOS / Linux runners
- Triggered by:
git worktree add ../wt -b feature; cd into the worktree; husky pre-push hook running pnpm changeset status --since=origin/main on push.
Workaround for affected users
Push from the main checkout (worktrees share refs, so git push origin feature-branch from the main repo hits the same remote without setting the worktree GIT_DIR). No project-file changes required.
Affected Packages
@changesets/cli@changesets/gitSummary
When a pre-push hook runs
changeset status --since=<ref>from inside a git worktree, the command spuriously fails with:The same command run directly from a shell in the same directory succeeds and reports the expected packages-to-be-bumped. Root cause:
gitinvokes hooks withGIT_DIRset to the worktree-specific git directory (e.g.,<repo>/.git/worktrees/<name>) but does not setGIT_WORK_TREE. Changesets CLI's internalgit diff/git ls-treeinvocations then resolve the working tree incorrectly and return an empty list of changed changeset files, even though the.changeset/*.mdfile is present inHEAD.Repro (minimal, env-var only)
In any repo with Changesets and an existing changeset file on a feature branch:
The minimal hook reproduction adds the wrinkle that git push sets
GIT_DIRautomatically inside a worktree, so users hit this without any explicit env setup — only on their non-main worktree pushes, and only when--since=<ref>is used.Where I traced it
getChangedChangesetFilesSinceRefin@changesets/gitspawns:With
GIT_DIRinherited andGIT_WORK_TREEunset, this returns an empty/incorrect file list — git can't resolve the work tree becauseGIT_DIRoverrides cwd-based discovery but the partner var isn't there to anchor it.filterChangesetsSinceRefin@changesets/readthen filters out every present.changeset/*.md(because none match the now-empty "changed files since ref" set), sochangesets.length === 0and thestatuscommand reports "no changesets were found" despite the file being on disk and committed in HEAD.Suggested fix
In
@changesets/git, either:GIT_DIRin the childgitspawns (let git auto-discover from the passedcwd), orGIT_WORK_TREEalongside the inheritedGIT_DIRwhen callingspawn("git", ...).Option 1 is the more conservative fix and aligns with the existing
cwdparameter already being passed to everyspawncall. The current code implicitly assumes git will usecwdfor working-tree resolution, which holds only whenGIT_DIRis also unset or paired withGIT_WORK_TREE.Environment
@changesets/cli2.31.0 /@changesets/git3.0.4git worktree add ../wt -b feature; cd into the worktree; husky pre-push hook runningpnpm changeset status --since=origin/mainon push.Workaround for affected users
Push from the main checkout (worktrees share refs, so
git push origin feature-branchfrom the main repo hits the same remote without setting the worktreeGIT_DIR). No project-file changes required.