From 214b7e070f9ebc456bd0d9f1d768d78b76c706de Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 3 Jun 2026 06:45:48 -0700 Subject: [PATCH] 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. --- scripts/install.ps1 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 63d90b4dec0..318508da1df 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -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