diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go
index 7920c07056..99a44dff0f 100644
--- a/services/migrations/gitea_uploader.go
+++ b/services/migrations/gitea_uploader.go
@@ -492,10 +492,16 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
 			}
 		case issues_model.CommentTypeChangeTitle:
 			if comment.Meta["OldTitle"] != nil {
-				cm.OldTitle = fmt.Sprintf("%s", comment.Meta["OldTitle"])
+				cm.OldTitle = fmt.Sprint(comment.Meta["OldTitle"])
 			}
 			if comment.Meta["NewTitle"] != nil {
-				cm.NewTitle = fmt.Sprintf("%s", comment.Meta["NewTitle"])
+				cm.NewTitle = fmt.Sprint(comment.Meta["NewTitle"])
+			}
+		case issues_model.CommentTypeChangeTargetBranch:
+			if comment.Meta["OldRef"] != nil && comment.Meta["NewRef"] != nil {
+				cm.OldRef = fmt.Sprint(comment.Meta["OldRef"])
+				cm.NewRef = fmt.Sprint(comment.Meta["NewRef"])
+				cm.Content = ""
 			}
 		case issues_model.CommentTypePRScheduledToAutoMerge, issues_model.CommentTypePRUnScheduledToAutoMerge:
 			cm.Content = ""
diff --git a/services/migrations/gitlab.go b/services/migrations/gitlab.go
index d08eaf0f84..5e49ae6d57 100644
--- a/services/migrations/gitlab.go
+++ b/services/migrations/gitlab.go
@@ -11,6 +11,7 @@ import (
 	"net/http"
 	"net/url"
 	"path"
+	"regexp"
 	"strings"
 	"time"
 
@@ -519,6 +520,8 @@ func (g *GitlabDownloader) GetComments(commentable base.Commentable) ([]*base.Co
 	return allComments, true, nil
 }
 
+var targetBranchChangeRegexp = regexp.MustCompile("^changed target branch from `(.*?)` to `(.*?)`$")
+
 func (g *GitlabDownloader) convertNoteToComment(localIndex int64, note *gitlab.Note) *base.Comment {
 	comment := &base.Comment{
 		IssueIndex:  localIndex,
@@ -528,11 +531,16 @@ func (g *GitlabDownloader) convertNoteToComment(localIndex int64, note *gitlab.N
 		PosterEmail: note.Author.Email,
 		Content:     note.Body,
 		Created:     *note.CreatedAt,
+		Meta:        map[string]any{},
 	}
 
 	// Try to find the underlying event of system notes.
 	if note.System {
-		if strings.HasPrefix(note.Body, "enabled an automatic merge") {
+		if match := targetBranchChangeRegexp.FindStringSubmatch(note.Body); match != nil {
+			comment.CommentType = issues_model.CommentTypeChangeTargetBranch.String()
+			comment.Meta["OldRef"] = match[1]
+			comment.Meta["NewRef"] = match[2]
+		} else if strings.HasPrefix(note.Body, "enabled an automatic merge") {
 			comment.CommentType = issues_model.CommentTypePRScheduledToAutoMerge.String()
 		} else if note.Body == "canceled the automatic merge" {
 			comment.CommentType = issues_model.CommentTypePRUnScheduledToAutoMerge.String()
diff --git a/services/migrations/gitlab_test.go b/services/migrations/gitlab_test.go
index d941cebd2c..6e5ab86720 100644
--- a/services/migrations/gitlab_test.go
+++ b/services/migrations/gitlab_test.go
@@ -586,7 +586,8 @@ func TestNoteToComment(t *testing.T) {
 	notes := []gitlab.Note{
 		makeTestNote(1, "This is a regular comment", false),
 		makeTestNote(2, "enabled an automatic merge for abcd1234", true),
-		makeTestNote(3, "canceled the automatic merge", true),
+		makeTestNote(3, "changed target branch from `master` to `main`", true),
+		makeTestNote(4, "canceled the automatic merge", true),
 	}
 	comments := []base.Comment{{
 		IssueIndex:  17,
@@ -597,6 +598,7 @@ func TestNoteToComment(t *testing.T) {
 		CommentType: "",
 		Content:     "This is a regular comment",
 		Created:     now,
+		Meta:        map[string]any{},
 	}, {
 		IssueIndex:  17,
 		Index:       2,
@@ -606,15 +608,30 @@ func TestNoteToComment(t *testing.T) {
 		CommentType: "pull_scheduled_merge",
 		Content:     "enabled an automatic merge for abcd1234",
 		Created:     now,
+		Meta:        map[string]any{},
 	}, {
 		IssueIndex:  17,
 		Index:       3,
 		PosterID:    72,
 		PosterName:  "test",
 		PosterEmail: "test@example.com",
+		CommentType: "change_target_branch",
+		Content:     "changed target branch from `master` to `main`",
+		Created:     now,
+		Meta: map[string]any{
+			"OldRef": "master",
+			"NewRef": "main",
+		},
+	}, {
+		IssueIndex:  17,
+		Index:       4,
+		PosterID:    72,
+		PosterName:  "test",
+		PosterEmail: "test@example.com",
 		CommentType: "pull_cancel_scheduled_merge",
 		Content:     "canceled the automatic merge",
 		Created:     now,
+		Meta:        map[string]any{},
 	}}
 
 	for i, note := range notes {
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index cf9df4dbda..20dbbdc6e4 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -369,8 +369,7 @@
 		{{else if eq .Type 22}}
 			<div class="timeline-item-group" id="{{.HashTag}}">
 				<div class="timeline-item event">
-					{{if .OriginalAuthor}}
-					{{else}}
+					{{if not .OriginalAuthor}}
 					{{/* Some timeline avatars need a offset to correctly align with their speech
 							bubble. The condition depends on review type and for positive reviews whether
 							there is a comment element or not */}}
@@ -499,9 +498,21 @@
 		{{else if eq .Type 25}}
 			<div class="timeline-item event">
 				<span class="badge">{{svg "octicon-git-branch"}}</span>
-				{{template "shared/user/avatarlink" dict "user" .Poster}}
+				{{if not .OriginalAuthor}}
+					{{template "shared/user/avatarlink" dict "user" .Poster}}
+				{{end}}
 				<span class="text grey muted-links">
-					<a{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>{{.Poster.Name}}</a>
+					{{if .OriginalAuthor}}
+						<span class="text black">
+							{{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
+							{{.OriginalAuthor}}
+						</span>
+						{{if $.Repository.OriginalURL}}
+						<span class="migrate">({{ctx.Locale.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname}})</span>
+						{{end}}
+					{{else}}
+						{{template "shared/user/authorlink" .Poster}}
+					{{end}}
 					{{ctx.Locale.Tr "repo.pulls.change_target_branch_at" (.OldRef|Escape) (.NewRef|Escape) $createdStr}}
 				</span>
 			</div>