fix(pull): fetch PR head refs instead of pushing them (#39603) (#39607)

Backport https://github.com/go-gitea/gitea/pull/39603 by @silverwind

Uses `FetchRemoteCommit`, as v28 has no `FetchRemoteTempCommit`, so no
`--no-write-fetch-head` is involved.
This commit is contained in:
silverwind authored and GitHub committed 2026-10-05 20:31:46 +02:00
1 parent 08c123299a
commit e66e773a6f
2 files changed
+13 -33

No files matched your search

+11 -18
View File
@@ -556,11 +556,10 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest,
return false, mergeBase, nil
}
// PushToBaseRepo pushes commits from branches of head repository to
// corresponding branches of base repository.
// FIXME: Only push branches that are actually updates?
// PushToBaseRepo fetches the head branch commit into the base repository and points the PR head ref at it.
// FIXME: Only update refs that actually changed?
func PushToBaseRepo(ctx context.Context, pr *issues_model.PullRequest) error {
log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitHeadRefName())
log.Trace("PushToBaseRepo[%d]: updating base repo ref '%s'", pr.BaseRepoID, pr.GetGitHeadRefName())
if err := pr.LoadHeadRepo(ctx); err != nil {
return err
@@ -571,23 +570,17 @@ func PushToBaseRepo(ctx context.Context, pr *issues_model.PullRequest) error {
if err := pr.LoadIssue(ctx); err != nil {
return err
}
if err := pr.Issue.LoadPoster(ctx); err != nil {
headCommitID, err := git.GetFullCommitID(ctx, pr.HeadRepo, git.BranchPrefix+pr.HeadBranch)
if err != nil {
return err
}
baseRepoHeadRefName := pr.GetGitHeadRefName()
if err := git.PushManaged(ctx, pr.HeadRepo, pr.BaseRepo, git.PushOptions{
Branch: git.BranchPrefix + pr.HeadBranch + ":" + baseRepoHeadRefName,
Force: true,
// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/...
Env: repo_module.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo),
}); err != nil {
// Since we use internal force-push, there should be no git error.
// If any error happens, it must be an internal error (e.g.: broken git hooks) but not user error.
return fmt.Errorf("unable to push from head branch %s:%s to base repo %s:%s, err: %w",
pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), baseRepoHeadRefName, err)
// fetch, not push: pushing objects FetchRemoteCommit already fetched races background repacks
if err := git.FetchRemoteCommit(ctx, pr.BaseRepo, pr.HeadRepo, headCommitID); err != nil {
return fmt.Errorf("unable to fetch head branch %s:%s into base repo %s, err: %w",
pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), err)
}
return nil
return git.UpdateRef(ctx, pr.BaseRepo, pr.GetGitHeadRefName(), headCommitID)
}
// UpdatePullsRefs update all the PRs head file pointers like /refs/pull/1/head so that it will be dependent by other operations