From bab21b2b06c7a8e87861f13cc8ba25d37a6e805b Mon Sep 17 00:00:00 2001 From: KellyMichels Date: Thu, 13 Aug 2026 19:33:47 -0500 Subject: [PATCH] fix(zdeploy): sync via explicit fetch + ff-only merge, not git pull With deploy.gitPull set, Invoke-DeployGitPull ran `git pull --ff-only`. Pull merges whatever .git/FETCH_HEAD marks "for merge", and a concurrent fetch in the same repo - an editor's background auto-fetch racing the deploy - can leave duplicate for-merge lines. Pull then dies with "Cannot fast-forward to multiple branches" even when both lines name the same commit. Reproduced live on 2026-08-13: the deploy failed at step 0, and by inspection time the same pull succeeded, with the duplicated FETCH_HEAD entries as the only evidence. Now the function fetches explicitly and fast-forwards against the remote-tracking ref: git fetch origin git merge --ff-only origin/$branch Identical fast-forward-or-refuse semantics, but nothing shared and mutable in the path. A failed fetch and a failed merge now also throw distinct messages, so the operator knows which half broke. CHECKSUMS.txt refreshed alongside, per the manifest rule. Tested: PS 5.1 parse clean; full Pester suite 222/222 after the manifest refresh (the 3 pre-refresh failures were the checksum suite correctly flagging the edited file). The same fix pattern was exercised against live and scratch repos for the private twin (evomedia-net/evo.scripts#58): behind -> fast-forwards, diverged -> refuses and aborts the deploy. Closes #48 --- CHECKSUMS.txt | 2 +- ZHelpers.ps1 | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHECKSUMS.txt b/CHECKSUMS.txt index 93a3bfb..6bc6ebc 100644 --- a/CHECKSUMS.txt +++ b/CHECKSUMS.txt @@ -15,7 +15,7 @@ c92343ce16e82210bfbdccd6ea7866ee4f0b2e0f035cf9605aa6bb35c0ba5209 zec2.cmd af3d16e3f49b61ad1d31130a0d2c8bc2235c0319a4b67585f06a1ca684ecec65 zec2_rotatekeys.ps1 4b5c24e9fdc7963d3ac4bddb69f93850adc5a43d8b18b6e948d7e8a768e2765a zec2online.cmd 9d5cbf647c5e4f49a1fb0a42bd8746ac2e72f3db639ef2d3be31d7c6fe8582ef zec2online.ps1 -8b842b31b5f12e2f225480dee904a39d0cc816b1f53c33ef2f14dc0210f8b670 ZHelpers.ps1 +8d70ff9d6dd3211461af4e1531c205414972756af44b88cd6c146852a51f82a2 ZHelpers.ps1 0a4ff2f6f220d9bde73ac19c0e19bbf5abf338f11f15bd22b90d788dabd6d9b2 zkill.cmd 8172c4d8d2c64aa1ec4b6a1a4983aece3277e248b510994b116c3024ef661874 zkill.ps1 1b25ce0848d22e1ac579287fac05da21458b59b94e09ed192282ac548516a3ce ZKiller.ps1 diff --git a/ZHelpers.ps1 b/ZHelpers.ps1 index d21d628..cf771c3 100644 --- a/ZHelpers.ps1 +++ b/ZHelpers.ps1 @@ -194,14 +194,24 @@ function Invoke-DeployGitPull { Write-Host " gitPull set but '$root' is not a git repo - skipping pull." -ForegroundColor Yellow return } - Write-Host "`n--- [0] git pull --ff-only ---" -ForegroundColor Cyan + Write-Host "`n--- [0] git sync (fetch + ff-only merge) ---" -ForegroundColor Cyan Push-Location -LiteralPath $root try { $branch = (git rev-parse --abbrev-ref HEAD) Write-Host " Branch: $branch" -ForegroundColor DarkGray - git pull --ff-only + # Fetch explicitly, then fast-forward against the remote-tracking ref - + # not `git pull`. Pull merges whatever FETCH_HEAD marks "for merge", + # and a concurrent fetch in the same repo (an editor's background + # auto-fetch racing the deploy) can leave duplicate for-merge lines, + # killing the run with "Cannot fast-forward to multiple branches" even + # when both lines name the same commit. origin/$branch is unambiguous. + git fetch origin if ($LASTEXITCODE -ne 0) { - throw "git pull --ff-only failed in '$root' (branch '$branch'). Resolve it (commit / stash / reconcile), then re-run - refusing to deploy possibly-stale code." + throw "git fetch failed in '$root'. Check the remote, then re-run - refusing to deploy possibly-stale code." + } + git merge --ff-only "origin/$branch" + if ($LASTEXITCODE -ne 0) { + throw "git merge --ff-only origin/$branch failed in '$root'. Resolve it (commit / stash / reconcile), then re-run - refusing to deploy possibly-stale code." } Write-Host " Now at: $(git log -1 --oneline)" -ForegroundColor DarkGray }