Use merge tree to detect conflicts when possible (#36400)

In Git 2.38, the `merge-tree` command introduced the `--write-tree`
option, which works directly on bare repositories. In Git 2.40, a new parameter `--merge-base` introduced so we require Git 2.40 to use the merge tree feature.

This option produces the merged tree object ID, allowing us to perform
diffs between commits without creating a temporary repository. By
avoiding the overhead of setting up and tearing down temporary repos,
this approach delivers a notable performance improvement.

It also fixes a possible situation that conflict files might be empty
but it's a conflict status according to
https://git-scm.com/docs/git-merge-tree#_mistakes_to_avoid

Replace #35542

---------

Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Lunny Xiao
2026-01-27 11:57:20 -08:00
committed by GitHub
parent 125257eacf
commit 1463426a27
29 changed files with 607 additions and 126 deletions
+6 -11
View File
@@ -90,16 +90,7 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error {
}
}
prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
if err != nil {
if !git_model.IsErrBranchNotExist(err) {
log.Error("CreateTemporaryRepoForPR %-v: %v", pr, err)
}
return err
}
defer cancel()
if err := testPullRequestTmpRepoBranchMergeable(ctx, prCtx, pr); err != nil {
if err := checkPullRequestBranchMergeable(ctx, pr); err != nil {
return err
}
@@ -128,6 +119,7 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error {
pr.Issue = issue
issue.PullRequest = pr
var err error
if pr.Flow == issues_model.PullRequestFlowGithub {
err = PushToBaseRepo(ctx, pr)
} else {
@@ -168,6 +160,9 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error {
// Request reviews, these should be requested before other notifications because they will add request reviews record
// on database
permDoer, err := access_model.GetUserRepoPermission(ctx, repo, issue.Poster)
if err != nil {
return err
}
for _, reviewer := range opts.Reviewers {
if _, err = issue_service.ReviewRequest(ctx, pr.Issue, issue.Poster, &permDoer, reviewer, true); err != nil {
return err
@@ -301,7 +296,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
pr.BaseBranch = targetBranch
// Refresh patch
if err := testPullRequestBranchMergeable(pr); err != nil {
if err := checkPullRequestBranchMergeable(ctx, pr); err != nil {
return err
}