fix(install.ps1): handle dirty worktree on Windows update (#38239)

Git for Windows defaults to core.autocrlf=true, which renormalizes the
repo's LF-only text files to CRLF in the working tree. On a managed,
never-user-edited clone this makes tracked files (.envrc, AGENTS.md,
agent/*.py, workflows) show as locally modified, so the update path's
bare git checkout aborts with 'Your local changes would be overwritten
by checkout' and the desktop bootstrap fails at stage=repository.

The bash installer already autostashes before checkout; the PowerShell
path had no dirty-tree handling at all and never pinned autocrlf.

Fix: (1) git reset --hard HEAD before fetch/checkout in the update path
to discard any pre-existing dirt, and (2) pin core.autocrlf=false on both
the update and fresh-clone paths so the dirt is never created again.
This commit is contained in:
Teknium 2026-06-03 06:45:48 -07:00 committed by GitHub
parent 6ee046a72f
commit 214b7e070f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1044,6 +1044,19 @@ function Install-Repository {
$prevEAP = $ErrorActionPreference
$ErrorActionPreference = "Continue"
try {
# This is a MANAGED checkout, not a repo the user edits. Git for
# Windows defaults to core.autocrlf=true, which renormalizes the
# repo's LF-only text files to CRLF in the working tree -- so
# tracked files (.envrc, AGENTS.md, agent/*.py, workflows, ...)
# show as locally modified even though nobody touched them. A
# bare `git checkout` then aborts with "Your local changes would
# be overwritten by checkout", which is exactly the failure GUI
# users hit on update. Two-part fix: (1) stop creating the dirt
# by pinning autocrlf=false on this clone, (2) discard any
# pre-existing dirt with a hard reset before the checkout. Safe
# because nothing here is user-authored.
git -c windows.appendAtomically=false config core.autocrlf false 2>$null
git -c windows.appendAtomically=false reset --hard HEAD 2>$null
git -c windows.appendAtomically=false fetch origin
if ($LASTEXITCODE -ne 0) { throw "git fetch failed (exit $LASTEXITCODE)" }
# Precedence: Commit > Tag > Branch. Commit and Tag check
@ -1178,6 +1191,11 @@ function Install-Repository {
# Set per-repo config (harmless if it fails)
Push-Location $InstallDir
git -c windows.appendAtomically=false config windows.appendAtomically false 2>$null
# Pin autocrlf=false on the managed clone so git never renormalizes the
# repo's LF text files to CRLF in the working tree. Without this, the very
# next `hermes update` checkout aborts on a "dirty" tree the user never
# touched (see the update path above).
git -c windows.appendAtomically=false config core.autocrlf false 2>$null
# Post-clone pin: when a clone (or ZIP-fallback init) just landed us on
# $Branch's tip, honour the higher-precedence $Commit / $Tag by checking