The windows installer kept the old tree when origin/$Branch could not
fast-forward:
git -C $InstallDir pull --ff-only origin $Branch
if ($LASTEXITCODE) { Log "not fast-forwardable; keeping local state" }
Every stage after that reads files only the new tree has (pm/lock.json and
friends), so an install left on the old tree cannot finish -- it died in
HEAD's install.ps1 reading a pm/ file that only exists on the new tree.
This is not hypothetical: the v2026.5.29.2 tag's commit is NOT an ancestor
of main (merge-base e71a2bd11b, 2 commits to the tag, 27435 to HEAD), so
anyone who installed from that release diverges the moment they re-run the
installer. install.sh already handles exactly this case, and says why:
# A release cut off the main line ... cannot fast-forward. Every stage
# below reads files only the new tree has (pm/), so an install left on
# the old tree cannot finish -- match the remote the way `hermes update`
# does, after parking the old tip and any local work.
Port that behaviour: merge --ff-only, and on failure stash local changes,
back up the previous HEAD to refs/hermes-install-backup/<stamp>-<prior>,
then reset --hard origin/$Branch.
Verified: pwsh's own parser accepts the file (PARSE OK, 4442 tokens).