fix(pull): don't auto-detect empty pull requests as manually merged (#39807)

With "Autodetect manual merge" enabled, an empty pull request (one with
no commits of its own, for example opened to discuss a branch) was
closed as manually merged as soon as it was checked. Its head commit is
already an ancestor of the base branch, so the detection took the
"fast-forwarded" path and recorded the head itself as the merge commit,
even though nothing was merged.

Detection now skips a PR whose head commit is its merge base, the same
condition Gitea already uses to show a PR as "already included in the
target branch". Real manual merges are still detected, including when
the base branch and the PR branch are pushed together.

The merge base is refreshed on recheck, so a fast-forward manual merge
whose merge base was already refreshed to the head is not detected
either. This only misses a detection and never closes a PR wrongly;
telling the two apart would need a value stored at PR creation.

Fixes https://github.com/go-gitea/gitea/issues/31947

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Mitrahsoftandwxiaoguang authored and GitHub committed 2026-10-16 08:29:25 -07:00
1 parent 2fe74d3cdd
commit 6b252ca3a9
2 files changed
+19 -8

No files matched your search

+11
View File
@@ -5,6 +5,7 @@ package integration
import (
"fmt"
"net/http"
"net/url"
"strings"
"testing"
@@ -16,6 +17,7 @@ import (
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/queue"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
@@ -59,6 +61,10 @@ func TestManualMergeAutodetect(t *testing.T) {
require.NoError(t, err)
}
testAPICreateBranch(t, user2Ctx.Session, user2.Name, repoName, defaultBranch, "empty-pr", http.StatusCreated)
emptyAPIPull, err := doAPICreatePullRequest(user1Ctx, user2.Name, repoName, defaultBranch, "empty-pr")(t)
require.NoError(t, err)
// user1 clones, then merges every branch sequentially, then pushes once.
// The first merge fast-forwards; the rest produce real merge commits,
// which generates multiple commits for "git rev-list --ancestry-path --merges ...".
@@ -100,5 +106,10 @@ func TestManualMergeAutodetect(t *testing.T) {
assert.Equalf(t, user1.ID, pr.MergerID, "PR %d (%s) merger should be the pusher", i+1, branchNames[i])
assert.Equalf(t, expectedMergeCommits[i], pr.MergedCommitID, "PR %d (%s) should be attributed to its own merge commit, not another PR's", i+1, branchNames[i])
}
require.NoError(t, queue.GetManager().FlushAll(t.Context(), 5*time.Second))
emptyPR := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: emptyAPIPull.ID})
assert.False(t, emptyPR.HasMerged, "empty PR must not be detected as manually merged")
assert.Equal(t, issues_model.PullRequestStatusAncestor, emptyPR.Status)
})
}