diff --git a/models/pull.go b/models/pull.go
index 33adc3214..3af51112d 100644
--- a/models/pull.go
+++ b/models/pull.go
@@ -7,8 +7,6 @@ package models
 
 import (
 	"fmt"
-	"os"
-	"path"
 	"strings"
 
 	"code.gitea.io/gitea/modules/git"
@@ -631,48 +629,6 @@ func (pr *PullRequest) UpdateCols(cols ...string) error {
 	return err
 }
 
-// PushToBaseRepo pushes commits from branches of head repository to
-// corresponding branches of base repository.
-// FIXME: Only push branches that are actually updates?
-func (pr *PullRequest) PushToBaseRepo() (err error) {
-	log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName())
-
-	headRepoPath := pr.HeadRepo.RepoPath()
-	headGitRepo, err := git.OpenRepository(headRepoPath)
-	if err != nil {
-		return fmt.Errorf("OpenRepository: %v", err)
-	}
-	defer headGitRepo.Close()
-
-	tmpRemoteName := fmt.Sprintf("tmp-pull-%d", pr.ID)
-	if err = headGitRepo.AddRemote(tmpRemoteName, pr.BaseRepo.RepoPath(), false); err != nil {
-		return fmt.Errorf("headGitRepo.AddRemote: %v", err)
-	}
-	// Make sure to remove the remote even if the push fails
-	defer func() {
-		if err := headGitRepo.RemoveRemote(tmpRemoteName); err != nil {
-			log.Error("PushToBaseRepo: RemoveRemote: %s", err)
-		}
-	}()
-
-	headFile := pr.GetGitRefName()
-
-	// Remove head in case there is a conflict.
-	file := path.Join(pr.BaseRepo.RepoPath(), headFile)
-
-	_ = os.Remove(file)
-
-	if err = git.Push(headRepoPath, git.PushOptions{
-		Remote: tmpRemoteName,
-		Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile),
-		Force:  true,
-	}); err != nil {
-		return fmt.Errorf("Push: %v", err)
-	}
-
-	return nil
-}
-
 // IsWorkInProgress determine if the Pull Request is a Work In Progress by its title
 func (pr *PullRequest) IsWorkInProgress() bool {
 	if err := pr.LoadIssue(); err != nil {
diff --git a/models/pull_test.go b/models/pull_test.go
index 6f799c1c8..325818e0b 100644
--- a/models/pull_test.go
+++ b/models/pull_test.go
@@ -190,8 +190,6 @@ func TestPullRequest_UpdateCols(t *testing.T) {
 	CheckConsistencyFor(t, pr)
 }
 
-// TODO TestPullRequest_PushToBaseRepo
-
 func TestPullRequestList_LoadAttributes(t *testing.T) {
 	assert.NoError(t, PrepareTestDatabase())
 
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index 93fa6ad27..1c273b7dc 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -307,9 +307,6 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption
 		}
 		ctx.Error(500, "NewPullRequest", err)
 		return
-	} else if err := pr.PushToBaseRepo(); err != nil {
-		ctx.Error(500, "PushToBaseRepo", err)
-		return
 	}
 
 	notification.NotifyNewPullRequest(pr)
diff --git a/routers/repo/pull.go b/routers/repo/pull.go
index c791bc55d..559d9b267 100644
--- a/routers/repo/pull.go
+++ b/routers/repo/pull.go
@@ -813,9 +813,6 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
 		}
 		ctx.ServerError("NewPullRequest", err)
 		return
-	} else if err := pullRequest.PushToBaseRepo(); err != nil {
-		ctx.ServerError("PushToBaseRepo", err)
-		return
 	}
 
 	notification.NotifyNewPullRequest(pullRequest)
diff --git a/services/pull/pull.go b/services/pull/pull.go
index df44402ad..6447c8a87 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -6,6 +6,8 @@ package pull
 
 import (
 	"fmt"
+	"os"
+	"path"
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/git"
@@ -33,6 +35,10 @@ func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int6
 	pr.Issue = pull
 	pull.PullRequest = pr
 
+	if err := PushToBaseRepo(pr); err != nil {
+		return err
+	}
+
 	notification.NotifyNewPullRequest(pr)
 
 	return nil
@@ -60,7 +66,7 @@ func checkForInvalidation(requests models.PullRequestList, repoID int64, doer *m
 func addHeadRepoTasks(prs []*models.PullRequest) {
 	for _, pr := range prs {
 		log.Trace("addHeadRepoTasks[%d]: composing new test task", pr.ID)
-		if err := pr.PushToBaseRepo(); err != nil {
+		if err := PushToBaseRepo(pr); err != nil {
 			log.Error("PushToBaseRepo: %v", err)
 			continue
 		}
@@ -107,3 +113,45 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy
 		AddToTaskQueue(pr)
 	}
 }
+
+// PushToBaseRepo pushes commits from branches of head repository to
+// corresponding branches of base repository.
+// FIXME: Only push branches that are actually updates?
+func PushToBaseRepo(pr *models.PullRequest) (err error) {
+	log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName())
+
+	headRepoPath := pr.HeadRepo.RepoPath()
+	headGitRepo, err := git.OpenRepository(headRepoPath)
+	if err != nil {
+		return fmt.Errorf("OpenRepository: %v", err)
+	}
+	defer headGitRepo.Close()
+
+	tmpRemoteName := fmt.Sprintf("tmp-pull-%d", pr.ID)
+	if err = headGitRepo.AddRemote(tmpRemoteName, pr.BaseRepo.RepoPath(), false); err != nil {
+		return fmt.Errorf("headGitRepo.AddRemote: %v", err)
+	}
+	// Make sure to remove the remote even if the push fails
+	defer func() {
+		if err := headGitRepo.RemoveRemote(tmpRemoteName); err != nil {
+			log.Error("PushToBaseRepo: RemoveRemote: %s", err)
+		}
+	}()
+
+	headFile := pr.GetGitRefName()
+
+	// Remove head in case there is a conflict.
+	file := path.Join(pr.BaseRepo.RepoPath(), headFile)
+
+	_ = os.Remove(file)
+
+	if err = git.Push(headRepoPath, git.PushOptions{
+		Remote: tmpRemoteName,
+		Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile),
+		Force:  true,
+	}); err != nil {
+		return fmt.Errorf("Push: %v", err)
+	}
+
+	return nil
+}
diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go
new file mode 100644
index 000000000..64920e355
--- /dev/null
+++ b/services/pull/pull_test.go
@@ -0,0 +1,8 @@
+// Copyright 2019 The Gitea Authors.
+// All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package pull
+
+// TODO TestPullRequest_PushToBaseRepo