fix(install): stop pinning managed checkouts to a single branch

`git clone --depth 1 --branch main` implies --single-branch, so every
managed install ends up with remote.origin.fetch pinned to main. On such
a checkout `git fetch origin <other>` updates FETCH_HEAD but never
creates origin/<other>, leaving other branches invisible to
`git branch -r` and `gh pr checkout`. install.sh made it stickier by
re-narrowing the refspec on every run, undoing manual fixes.

Restore the wildcard in both installers. It costs no bandwidth: naming
the branch is what makes a fetch cheap, and every fetch we issue does.
This commit is contained in:
Brooklyn Nicholson 2026-07-27 20:11:16 -05:00
parent f1af61354e
commit 4c602f2e05
3 changed files with 183 additions and 5 deletions

View file

@ -1761,6 +1761,13 @@ function Install-Repository {
# 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
# `clone --depth 1 --branch $Branch` implies --single-branch, which pins
# remote.origin.fetch to that one branch: `git fetch origin <other>` then
# updates FETCH_HEAD but never creates origin/<other>, so other branches
# are invisible to `git branch -r` / `gh pr checkout` and `hermes update
# --branch` fails. Restore the wildcard -- every fetch we issue names its
# branch, so nothing extra gets downloaded.
git -c windows.appendAtomically=false remote set-branches origin '*' 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

View file

@ -305,6 +305,22 @@ EOF
log_info "Discarded npm lockfile churn (${dirty_count} file(s))"
}
# `git clone --depth 1 --branch main` implies --single-branch, which pins
# remote.origin.fetch to main alone. On such a checkout `git fetch origin <b>`
# updates FETCH_HEAD but never creates origin/<b>, so other branches are
# invisible to `git branch -r` and `gh pr checkout`, and `hermes update
# --branch <b>` fails with "does not exist locally or on origin".
#
# Restoring the wildcard costs nothing: every fetch the installer and the CLI
# issue names its branch, and git only walks the full refspec on a bare
# `git fetch`. Also heals checkouts an older installer already narrowed.
widen_remote_branches() {
local repo="${1:-$INSTALL_DIR}"
[ -n "$repo" ] && [ -d "$repo/.git" ] || return 0
command -v git >/dev/null 2>&1 || return 0
git -C "$repo" remote set-branches origin '*' 2>/dev/null || true
}
emit_manifest() {
# Stage-Desktop is included only with --include-desktop, mirroring
# install.ps1: the signed bootstrap installer (Hermes-Setup) passes it so
@ -1210,11 +1226,11 @@ clone_repo() {
autostash_ref="stash@{0}"
fi
# Fetch only the target branch. A bare `git fetch origin` pulls
# every ref, and this repo carries thousands of auto-generated
# branches — on a non-single-branch checkout that turns each update
# into a multi-minute download that can stall the installer.
git remote set-branches origin "$BRANCH" 2>/dev/null || true
widen_remote_branches "$INSTALL_DIR"
# Naming the branch is what keeps the fetch cheap: a bare
# `git fetch origin` pulls every ref, and this repo carries
# thousands of branches, which turns each update into a
# multi-minute download that can stall the installer.
git fetch origin "$BRANCH"
git checkout "$BRANCH"
# Managed installs should follow origin/$BRANCH exactly. If the
@ -1304,6 +1320,7 @@ EOF
exit 1
fi
fi
widen_remote_branches "$INSTALL_DIR"
fi
cd "$INSTALL_DIR"