From 7a286e47532a31ed6abcde3a45da4bad1653a42e Mon Sep 17 00:00:00 2001
From: Brecht Van Lommel <brecht@blender.org>
Date: Wed, 25 Oct 2023 17:01:31 +0200
Subject: [PATCH] Improve pull request command line instructions (#27778)

* Show checkout instructions also when there is no permission to push,
for anyone who wants to locally test the changes.
* First checkout the branch exactly as is, without immediately having to
solve merge conflicts. Leave this to the merge step, since it's often
convenient to test a change without worrying about this.
* Use `git fetch -u`, so an existing local branch is updated when
re-testing the same pull request. But not the more risky `git fetch -f`
in to handle force pushes, as we don't want to accidentally overwrite
important local changes.
* Show different merge command depending on the chosen merge style,
interactively updated.
---
 options/locale/locale_en-US.ini               | 11 ++---
 templates/repo/issue/view_content/pull.tmpl   |  4 +-
 .../view_content/pull_merge_instruction.tmpl  | 46 +++++++++++++++----
 .../js/components/PullRequestMergeForm.vue    |  4 ++
 4 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index e3f2fcdd83..8dcce73b7d 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -110,9 +110,6 @@ write = Write
 preview = Preview
 loading = Loading…
 
-step1 = Step 1:
-step2 = Step 2:
-
 error = Error
 error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.
 go_back = Go Back
@@ -1797,9 +1794,11 @@ pulls.outdated_with_base_branch = This branch is out-of-date with the base branc
 pulls.close = Close Pull Request
 pulls.closed_at = `closed this pull request <a id="%[1]s" href="#%[1]s">%[2]s</a>`
 pulls.reopened_at = `reopened this pull request <a id="%[1]s" href="#%[1]s">%[2]s</a>`
-pulls.merge_instruction_hint = `You can also view <a class="show-instruction">command line instructions</a>.`
-pulls.merge_instruction_step1_desc = From your project repository, check out a new branch and test the changes.
-pulls.merge_instruction_step2_desc = Merge the changes and update on Gitea.
+pulls.cmd_instruction_hint = `View <a class="show-instruction">command line instructions</a>.`
+pulls.cmd_instruction_checkout_title = Checkout
+pulls.cmd_instruction_checkout_desc = From your project repository, check out a new branch and test the changes.
+pulls.cmd_instruction_merge_title = Merge
+pulls.cmd_instruction_merge_desc = Merge the changes and update on Gitea.
 pulls.clear_merge_message = Clear merge message
 pulls.clear_merge_message_hint = Clearing the merge message will only remove the commit message content and keep generated git trailers such as "Co-Authored-By …".
 
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl
index a4f7ede74d..2fed5848d5 100644
--- a/templates/repo/issue/view_content/pull.tmpl
+++ b/templates/repo/issue/view_content/pull.tmpl
@@ -372,8 +372,8 @@
 				</div>
 			{{end}}
 
-			{{if and .ShowMergeInstructions .Issue.PullRequest.HeadRepo (not .Issue.PullRequest.HasMerged) (not .Issue.IsClosed)}}
-				{{template "repo/issue/view_content/pull_merge_instruction" .Issue.PullRequest}}
+			{{if and .Issue.PullRequest.HeadRepo (not .Issue.PullRequest.HasMerged) (not .Issue.IsClosed)}}
+				{{template "repo/issue/view_content/pull_merge_instruction" dict "PullRequest" .Issue.PullRequest "ShowMergeInstructions" .ShowMergeInstructions}}
 			{{end}}
 		</div>
 	</div>
diff --git a/templates/repo/issue/view_content/pull_merge_instruction.tmpl b/templates/repo/issue/view_content/pull_merge_instruction.tmpl
index b1b52645e0..3dab44710e 100644
--- a/templates/repo/issue/view_content/pull_merge_instruction.tmpl
+++ b/templates/repo/issue/view_content/pull_merge_instruction.tmpl
@@ -1,19 +1,45 @@
 <div class="divider"></div>
-<div class="instruct-toggle"> {{ctx.Locale.Tr "repo.pulls.merge_instruction_hint" | Safe}} </div>
+<div class="instruct-toggle"> {{ctx.Locale.Tr "repo.pulls.cmd_instruction_hint" | Safe}} </div>
 <div class="instruct-content gt-mt-3 gt-hidden">
-	<div><h3 class="gt-dib">{{ctx.Locale.Tr "step1"}}</h3> {{ctx.Locale.Tr "repo.pulls.merge_instruction_step1_desc"}}</div>
+	<div><h3>{{ctx.Locale.Tr "repo.pulls.cmd_instruction_checkout_title"}}</h3>{{ctx.Locale.Tr "repo.pulls.cmd_instruction_checkout_desc"}}</div>
+	{{$localBranch := .PullRequest.HeadBranch}}
+	{{if ne .PullRequest.HeadRepo.ID .PullRequest.BaseRepo.ID}}
+		{{$localBranch = print .PullRequest.HeadRepo.OwnerName "-" .PullRequest.HeadBranch}}
+	{{end}}
 	<div class="ui secondary segment">
-		{{if eq .Flow 0}}
-		<div>git checkout -b {{if ne .HeadRepo.ID .BaseRepo.ID}}{{.HeadRepo.OwnerName}}-{{end}}{{.HeadBranch}} {{.BaseBranch}}</div>
-		<div>git pull {{if ne .HeadRepo.ID .BaseRepo.ID}}<gitea-origin-url data-url="{{.HeadRepo.Link}}"></gitea-origin-url>{{else}}origin{{end}} {{.HeadBranch}}</div>
+		{{if eq .PullRequest.Flow 0}}
+		<div>git fetch -u {{if ne .PullRequest.HeadRepo.ID .PullRequest.BaseRepo.ID}}<gitea-origin-url data-url="{{.PullRequest.HeadRepo.Link}}"></gitea-origin-url>{{else}}origin{{end}} {{.PullRequest.HeadBranch}}:{{$localBranch}}</div>
+		<div>git checkout {{$localBranch}}</div>
 		{{else}}
-		<div>git fetch origin {{.GetGitRefName}}:{{.HeadBranch}}</div>
+		<div>git fetch -u origin {{.GetGitRefName}}:{{$localBranch}}</div>
 		{{end}}
 	</div>
-	<div><h3 class="gt-dib">{{ctx.Locale.Tr "step2"}}</h3> {{ctx.Locale.Tr "repo.pulls.merge_instruction_step2_desc"}}</div>
+	{{if .ShowMergeInstructions}}
+	<div><h3>{{ctx.Locale.Tr "repo.pulls.cmd_instruction_merge_title"}}</h3>{{ctx.Locale.Tr "repo.pulls.cmd_instruction_merge_desc"}}</div>
 	<div class="ui secondary segment">
-		<div>git checkout {{.BaseBranch}}</div>
-		<div>git merge --no-ff {{if ne .HeadRepo.ID .BaseRepo.ID}}{{.HeadRepo.OwnerName}}-{{end}}{{.HeadBranch}}</div>
-		<div>git push origin {{.BaseBranch}}</div>
+		<div data-pull-merge-style="merge">
+			<div>git checkout {{.PullRequest.BaseBranch}}</div>
+			<div>git merge --no-ff {{$localBranch}}</div>
+		</div>
+		<div class="gt-hidden" data-pull-merge-style="rebase">
+			<div>git checkout {{.PullRequest.BaseBranch}}</div>
+			<div>git merge --ff-only {{$localBranch}}</div>
+		</div>
+		<div class="gt-hidden" data-pull-merge-style="rebase-merge">
+			<div>git checkout {{$localBranch}}</div>
+			<div>git rebase {{.PullRequest.BaseBranch}}</div>
+			<div>git checkout {{.PullRequest.BaseBranch}}</div>
+			<div>git merge --no-ff {{$localBranch}}</div>
+		</div>
+		<div class="gt-hidden" data-pull-merge-style="squash">
+			<div>git checkout {{.PullRequest.BaseBranch}}</div>
+			<div>git merge --squash {{$localBranch}}</div>
+		</div>
+		<div class="gt-hidden" data-pull-merge-style="manually-merged">
+			<div>git checkout {{.PullRequest.BaseBranch}}</div>
+			<div>git merge {{$localBranch}}</div>
+		</div>
+		<div>git push origin {{.PullRequest.BaseBranch}}</div>
 	</div>
+	{{end}}
 </div>
diff --git a/web_src/js/components/PullRequestMergeForm.vue b/web_src/js/components/PullRequestMergeForm.vue
index 03d1f99683..54dcf9d860 100644
--- a/web_src/js/components/PullRequestMergeForm.vue
+++ b/web_src/js/components/PullRequestMergeForm.vue
@@ -1,5 +1,6 @@
 <script>
 import {SvgIcon} from '../svg.js';
+import {toggleElem} from '../utils/dom.js';
 
 const {csrfToken, pageData} = window.config;
 
@@ -39,6 +40,9 @@ export default {
   watch: {
     mergeStyle(val) {
       this.mergeStyleDetail = this.mergeForm.mergeStyles.find((e) => e.name === val);
+      for (const elem of document.querySelectorAll('[data-pull-merge-style]')) {
+        toggleElem(elem, elem.getAttribute('data-pull-merge-style') === val);
+      }
     }
   },
   created() {