From 631f32cf95a176ff335001e07d7136b9b9ed82cc Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 20 Apr 2026 17:23:53 -0600 Subject: [PATCH] fix(gitshallow): mirror upstream with fetch+reset instead of pull --ff-only The shallow clone is a read-only mirror, so a force-push on the upstream branch caused pull --ff-only to bail with "refusing to merge unrelated histories". Switch to git fetch + git reset --hard origin/ so the local copy always tracks upstream, force-push or not. Auto-detects the branch from origin/HEAD when Branch is empty. --- net/gitshallow/gitshallow.go | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/net/gitshallow/gitshallow.go b/net/gitshallow/gitshallow.go index b5dca2d..0dc3385 100644 --- a/net/gitshallow/gitshallow.go +++ b/net/gitshallow/gitshallow.go @@ -115,7 +115,9 @@ func (r *Repo) runGit(args ...string) (string, error) { return strings.TrimSpace(string(output)), nil } -// Pull performs a shallow pull (--ff-only) and reports whether HEAD changed. +// Pull fetches from origin and hard-resets the working tree to the remote +// branch, reporting whether HEAD changed. This is a read-only mirror — we +// never try to merge, so force-pushes upstream are handled transparently. func (r *Repo) Pull() (updated bool, err error) { r.mu.Lock() defer r.mu.Unlock() @@ -127,19 +129,27 @@ func (r *Repo) pull() (updated bool, err error) { return false, fmt.Errorf("repository does not exist at %s", r.Path) } - oldHead, err := r.runGit("rev-parse", "HEAD") - if err != nil { + oldHead, _ := r.runGit("rev-parse", "HEAD") + + branch := r.Branch + if branch == "" { + out, err := r.runGit("symbolic-ref", "--short", "refs/remotes/origin/HEAD") + if err != nil { + return false, err + } + _, branch, _ = strings.Cut(out, "/") + } + + fetchArgs := []string{"fetch", "--no-tags"} + if depth := r.effectiveDepth(); depth >= 0 { + fetchArgs = append(fetchArgs, "--depth", fmt.Sprintf("%d", depth)) + } + fetchArgs = append(fetchArgs, "origin", branch) + if _, err := r.runGit(fetchArgs...); err != nil { return false, err } - pullArgs := []string{"pull", "--ff-only", "--no-tags"} - if depth := r.effectiveDepth(); depth >= 0 { - pullArgs = append(pullArgs, "--depth", fmt.Sprintf("%d", depth)) - } - if r.Branch != "" { - pullArgs = append(pullArgs, "origin", r.Branch) - } - if _, err = r.runGit(pullArgs...); err != nil { + if _, err := r.runGit("reset", "--hard", "origin/"+branch); err != nil { return false, err }