diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ac062496c..142390c89 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -3,7 +3,8 @@ ## New in git-machete 3.29.3 - changed: no longer publish RPM files with GitHub releases -- fixed: work around the parsing bug in `git patch-id` v2.46.1 +- fixed: work around the parsing bug in `git patch-id` v2.46.1 (reported by @ilai-deutel) +- fixed: `git machete git{hub,lab} create-{pr,mr}` takes into account `` in PR/MR template (suggested by @frank-west-iii) ## New in git-machete 3.29.2 diff --git a/docs/man/git-machete.1 b/docs/man/git-machete.1 index fcdfc035b..eff92837b 100644 --- a/docs/man/git-machete.1 +++ b/docs/man/git-machete.1 @@ -363,7 +363,7 @@ from the message body of the first unique commit of the branch, even if \fB\&.gi .B \fBmachete.github.prDescriptionIntroStyle\fP: .INDENT 7.0 .TP -.B Select the style of the intro prepended to PR description: +.B Select the style of the generated section (\(dqintro\(dq) added to the PR description: .INDENT 7.0 .IP \(bu 2 \fBfull\fP \-\-\- include both a chain of upstream PRs (typically leading to \fBmain\fP, \fBmaster\fP, \fBdevelop\fP etc.) and a tree of downstream PRs @@ -409,7 +409,7 @@ from the message body of the first unique commit of the branch, even if \fB\&.gi .B \fBmachete.gitlab.mrDescriptionIntroStyle\fP: .INDENT 7.0 .TP -.B Select the style of the intro prepended to MR description: +.B Select the style of the generated section (\(dqintro\(dq) added to the MR description: .INDENT 7.0 .IP \(bu 2 \fBfull\fP \-\-\- include both a chain of upstream MRs (typically leading to \fBmain\fP, \fBmaster\fP, \fBdevelop\fP etc.) and a tree of downstream MRs @@ -999,11 +999,13 @@ If \fB\&.git/info/milestone\fP file is present, its contents (a single number \- If \fB\&.git/info/reviewers\fP file is present, its contents (one GitHub login per line) are used to set reviewers. .sp The subject of the first unique commit of the branch is used as PR title. -If \fB\&.git/info/description\fP or \fB\&.github/pull_request_template.md\fP file is present, its contents are used as PR description. +If \fB\&.git/info/description\fP or \fB\&.github/pull_request_template.md\fP template is present, its contents are used as PR description. Otherwise (or if \fBmachete.github.forceDescriptionFromCommitMessage\fP is set), PR description is taken from message body of the first unique commit of the branch. .sp -If the newly\-created PR is stacked atop another PR, the actual PR description posted to GitHub will be prepended with a section -listing the entire related chain of PRs. +If the newly\-created PR is stacked atop another PR, the actual PR description posted to GitHub will include a generated section (\(dqintro\(dq) +listing the entire related chain of PRs. This section will be delimited with \fB\fP +and \fB\fP comments in Markdown. If a PR template file exists and contains these comments already, +the generated section will be placed between them; otherwise, it will be placed at the beginning. .sp \fBOptions:\fP .INDENT 7.0 @@ -1037,8 +1039,8 @@ Draft PRs don\(aqt get code owners automatically added as reviewers. .B \fBretarget\-pr [\-b|\-\-branch=] [\-\-ignore\-if\-missing]\fP: Sets the base of the current (or specified) branch\(aqs PR to upstream (parent) branch, as seen by git machete (see \fBgit machete show up\fP). .sp -If after changing the base the PR ends up stacked atop another PR, the PR description posted to GitHub will be prepended -with an intro section listing the entire related chain of PRs. +If after changing the base the PR ends up stacked atop another PR, the PR description posted to GitHub will include +a generated section (\(dqintro\(dq) listing the entire related chain of PRs. .sp This intro will be updated or removed accordingly with the subsequent runs of \fBretarget\-pr\fP, even if the base branch is already up to date. .sp @@ -1107,7 +1109,7 @@ from the message body of the first unique commit of the branch, even if \fB\&.gi .B \fBmachete.github.prDescriptionIntroStyle\fP (\fBcreate\-pr\fP, \fBrestack\-pr\fP and \fBretarget\-pr\fP): .INDENT 7.0 .TP -.B Select the style of the intro prepended to PR description: +.B Select the style of the generated section (\(dqintro\(dq) added to the PR description: .INDENT 7.0 .IP \(bu 2 \fBfull\fP \-\-\- include both a chain of upstream PRs (typically leading to \fBmain\fP, \fBmaster\fP, \fBdevelop\fP etc.) and a tree of downstream PRs @@ -1237,11 +1239,13 @@ Note that you need to use a global (not per\-project) milestone id. Look for som If \fB\&.git/info/reviewers\fP file is present, its contents (one GitLab login per line) are used to set reviewers. .sp The subject of the first unique commit of the branch is used as MR title. -If \fB\&.git/info/description\fP or \fB\&.gitlab/merge_request_templates/Default.md\fP file is present, its contents are used as MR description. +If \fB\&.git/info/description\fP or \fB\&.gitlab/merge_request_templates/Default.md\fP template is present, its contents are used as MR description. Otherwise (or if \fBmachete.gitlab.forceDescriptionFromCommitMessage\fP is set), MR description is taken from message body of the first unique commit of the branch. .sp -If the newly\-created MR is stacked atop another MR, the actual MR description posted to GitLab will be prepended with a section -listing the entire related chain of MRs. +If the newly\-created MR is stacked atop another MR, the actual MR description posted to GitLab will include a generated section (\(dqintro\(dq) +listing the entire related chain of MRs. This section will be delimited with \fB\fP +and \fB\fP comments in Markdown. If an MR template file exists and contains these comments already, +the generated section will be placed between them; otherwise, it will be placed at the beginning. .sp \fBOptions:\fP .INDENT 7.0 @@ -1275,8 +1279,8 @@ Draft MRs don\(aqt get code owners automatically added as reviewers. .B \fBretarget\-mr [\-b|\-\-branch=] [\-\-ignore\-if\-missing]\fP: Sets the target of the current (or specified) branch\(aqs MR to upstream (parent) branch, as seen by git machete (see \fBgit machete show up\fP). .sp -If after changing the target the MR ends up stacked atop another MR, the MR description posted to GitLab will be prepended -with an intro section listing the entire related chain of MRs. +If after changing the base the MR ends up stacked atop another MR, the MR description posted to GitLab will include +a generated section (\(dqintro\(dq) listing the entire related chain of MRs. .sp This intro will be updated or removed accordingly with the subsequent runs of \fBretarget\-mr\fP, even if the target branch is already up to date. .sp @@ -1331,7 +1335,7 @@ from the message body of the first unique commit of the branch, even if \fB\&.gi .B \fBmachete.gitlab.mrDescriptionIntroStyle\fP (\fBcreate\-mr\fP, \fBrestack\-mr\fP and \fBretarget\-mr\fP): .INDENT 7.0 .TP -.B Select the style of the intro prepended to MR description: +.B Select the style of the generated section (\(dqintro\(dq) added to the MR description: .INDENT 7.0 .IP \(bu 2 \fBfull\fP \-\-\- include both a chain of upstream MRs (typically leading to \fBmain\fP, \fBmaster\fP, \fBdevelop\fP etc.) and a tree of downstream MRs diff --git a/docs/source/cli/github.rst b/docs/source/cli/github.rst index 272f8c3d2..5e0667be2 100644 --- a/docs/source/cli/github.rst +++ b/docs/source/cli/github.rst @@ -84,11 +84,13 @@ Creates, checks out and manages GitHub PRs while keeping them reflected in branc If ``.git/info/reviewers`` file is present, its contents (one GitHub login per line) are used to set reviewers. The subject of the first unique commit of the branch is used as PR title. - If ``.git/info/description`` or ``.github/pull_request_template.md`` file is present, its contents are used as PR description. + If ``.git/info/description`` or ``.github/pull_request_template.md`` template is present, its contents are used as PR description. Otherwise (or if ``machete.github.forceDescriptionFromCommitMessage`` is set), PR description is taken from message body of the first unique commit of the branch. - If the newly-created PR is stacked atop another PR, the actual PR description posted to GitHub will be prepended with a section - listing the entire related chain of PRs. + If the newly-created PR is stacked atop another PR, the actual PR description posted to GitHub will include a generated section ("intro") + listing the entire related chain of PRs. This section will be delimited with ```` + and ```` comments in Markdown. If a PR template file exists and contains these comments already, + the generated section will be placed between them; otherwise, it will be placed at the beginning. **Options:** @@ -112,8 +114,8 @@ Creates, checks out and manages GitHub PRs while keeping them reflected in branc ``retarget-pr [-b|--branch=] [--ignore-if-missing]``: Sets the base of the current (or specified) branch's PR to upstream (parent) branch, as seen by git machete (see ``git machete show up``). - If after changing the base the PR ends up stacked atop another PR, the PR description posted to GitHub will be prepended - with an intro section listing the entire related chain of PRs. + If after changing the base the PR ends up stacked atop another PR, the PR description posted to GitHub will include + a generated section ("intro") listing the entire related chain of PRs. This intro will be updated or removed accordingly with the subsequent runs of ``retarget-pr``, even if the base branch is already up to date. diff --git a/docs/source/cli/gitlab.rst b/docs/source/cli/gitlab.rst index 947444b0e..a5d8bf4de 100644 --- a/docs/source/cli/gitlab.rst +++ b/docs/source/cli/gitlab.rst @@ -85,11 +85,13 @@ Creates, checks out and manages GitLab MRs while keeping them reflected in branc If ``.git/info/reviewers`` file is present, its contents (one GitLab login per line) are used to set reviewers. The subject of the first unique commit of the branch is used as MR title. - If ``.git/info/description`` or ``.gitlab/merge_request_templates/Default.md`` file is present, its contents are used as MR description. + If ``.git/info/description`` or ``.gitlab/merge_request_templates/Default.md`` template is present, its contents are used as MR description. Otherwise (or if ``machete.gitlab.forceDescriptionFromCommitMessage`` is set), MR description is taken from message body of the first unique commit of the branch. - If the newly-created MR is stacked atop another MR, the actual MR description posted to GitLab will be prepended with a section - listing the entire related chain of MRs. + If the newly-created MR is stacked atop another MR, the actual MR description posted to GitLab will include a generated section ("intro") + listing the entire related chain of MRs. This section will be delimited with ```` + and ```` comments in Markdown. If an MR template file exists and contains these comments already, + the generated section will be placed between them; otherwise, it will be placed at the beginning. **Options:** @@ -113,8 +115,8 @@ Creates, checks out and manages GitLab MRs while keeping them reflected in branc ``retarget-mr [-b|--branch=] [--ignore-if-missing]``: Sets the target of the current (or specified) branch's MR to upstream (parent) branch, as seen by git machete (see ``git machete show up``). - If after changing the target the MR ends up stacked atop another MR, the MR description posted to GitLab will be prepended - with an intro section listing the entire related chain of MRs. + If after changing the base the MR ends up stacked atop another MR, the MR description posted to GitLab will include + a generated section ("intro") listing the entire related chain of MRs. This intro will be updated or removed accordingly with the subsequent runs of ``retarget-mr``, even if the target branch is already up to date. diff --git a/docs/source/git-config-keys/github_prDescriptionIntroStyle.rst b/docs/source/git-config-keys/github_prDescriptionIntroStyle.rst index 2948906bb..ea149d920 100644 --- a/docs/source/git-config-keys/github_prDescriptionIntroStyle.rst +++ b/docs/source/git-config-keys/github_prDescriptionIntroStyle.rst @@ -1,4 +1,4 @@ -Select the style of the intro prepended to PR description: +Select the style of the generated section ("intro") added to the PR description: * ``full`` --- include both a chain of upstream PRs (typically leading to ``main``, ``master``, ``develop`` etc.) and a tree of downstream PRs * ``up-only`` --- default, include only a chain of upstream PRs * ``none`` --- prepend no intro to the PR description at all diff --git a/docs/source/git-config-keys/gitlab_mrDescriptionIntroStyle.rst b/docs/source/git-config-keys/gitlab_mrDescriptionIntroStyle.rst index 8465072d9..d19a8e454 100644 --- a/docs/source/git-config-keys/gitlab_mrDescriptionIntroStyle.rst +++ b/docs/source/git-config-keys/gitlab_mrDescriptionIntroStyle.rst @@ -1,4 +1,4 @@ -Select the style of the intro prepended to MR description: +Select the style of the generated section ("intro") added to the MR description: * ``full`` --- include both a chain of upstream MRs (typically leading to ``main``, ``master``, ``develop`` etc.) and a tree of downstream MRs * ``up-only`` --- default, include only a chain of upstream MRs * ``none`` --- prepend no intro to the MR description at all diff --git a/git_machete/client.py b/git_machete/client.py index 153016a30..1beb5bdd1 100644 --- a/git_machete/client.py +++ b/git_machete/client.py @@ -2465,11 +2465,12 @@ def skip_leading_empty(strs: List[str]) -> List[str]: start_index = lines.index(self.START_GIT_MACHETE_GENERATED_COMMENT) end_index = lines.index(self.END_GIT_MACHETE_GENERATED_COMMENT) lines = lines[:start_index] + lines_to_prepend + lines[end_index + 1:] + lines = skip_leading_empty(lines) else: # For compatibility with pre-v3.23.0 format; only affects GitHub if lines and '# Based on PR #' in lines[0]: - lines = skip_leading_empty(lines[1:]) - lines = lines_to_prepend + lines + lines = lines[1:] + lines = lines_to_prepend + ([''] if lines_to_prepend else []) + skip_leading_empty(lines) return '\n'.join(lines) def retarget_pr(self, spec: CodeHostingSpec, head: LocalBranchShortName, ignore_if_missing: bool) -> None: @@ -2792,14 +2793,11 @@ def create_pull_request( if base_branch_found_on_remote or style == PRDescriptionIntroStyle.FULL: # As the description may include the reference to this PR itself (in case of a chain of >=2 PRs), # let's update the PR description after it's already created (so that we know the current PR's number). - text_to_prepend = self.__generate_pr_description_intro(code_hosting_client, pr, style) - if text_to_prepend: - if description: - text_to_prepend += '\n' - description = text_to_prepend + description + new_description = self.__get_updated_pull_request_description(code_hosting_client, pr, description) + if new_description.strip() != description.strip(): print(f'Updating description of {pr.display_text()} to include ' f'the chain of {spec.pr_short_name}s... ', end='', flush=True) - code_hosting_client.set_description_of_pull_request(pr.number, description) + code_hosting_client.set_description_of_pull_request(pr.number, new_description) print(fmt(ok_str)) milestone_path: str = self.__git.get_main_git_subpath('info', 'milestone') diff --git a/git_machete/generated_docs.py b/git_machete/generated_docs.py index 4a7e90458..f7f0200af 100644 --- a/git_machete/generated_docs.py +++ b/git_machete/generated_docs.py @@ -251,7 +251,7 @@ `machete.github.prDescriptionIntroStyle`: - Select the style of the intro prepended to PR description: + Select the style of the generated section ("intro") added to the PR description: * `full` — include both a chain of upstream PRs (typically leading to `main`, `master`, `develop` etc.) and a tree of downstream PRs @@ -288,7 +288,7 @@ `machete.gitlab.mrDescriptionIntroStyle`: - Select the style of the intro prepended to MR description: + Select the style of the generated section ("intro") added to the MR description: * `full` — include both a chain of upstream MRs (typically leading to `main`, `master`, `develop` etc.) and a tree of downstream MRs @@ -639,11 +639,13 @@ If `.git/info/reviewers` file is present, its contents (one GitHub login per line) are used to set reviewers. The subject of the first unique commit of the branch is used as PR title. - If `.git/info/description` or `.github/pull_request_template.md` file is present, its contents are used as PR description. + If `.git/info/description` or `.github/pull_request_template.md` template is present, its contents are used as PR description. Otherwise (or if `machete.github.forceDescriptionFromCommitMessage` is set), PR description is taken from message body of the first unique commit of the branch. - If the newly-created PR is stacked atop another PR, the actual PR description posted to GitHub will be prepended with a section - listing the entire related chain of PRs. + If the newly-created PR is stacked atop another PR, the actual PR description posted to GitHub will include a generated section ("intro") + listing the entire related chain of PRs. This section will be delimited with `` + and `` comments in Markdown. If a PR template file exists and contains these comments already, + the generated section will be placed between them; otherwise, it will be placed at the beginning. Options: @@ -676,8 +678,8 @@ Sets the base of the current (or specified) branch's PR to upstream (parent) branch, as seen by git machete (see `git machete show up`). - If after changing the base the PR ends up stacked atop another PR, the PR description posted to GitHub will be prepended - with an intro section listing the entire related chain of PRs. + If after changing the base the PR ends up stacked atop another PR, the PR description posted to GitHub will include + a generated section ("intro") listing the entire related chain of PRs. This intro will be updated or removed accordingly with the subsequent runs of `retarget-pr`, even if the base branch is already up to date. @@ -737,7 +739,7 @@ `machete.github.prDescriptionIntroStyle` (`create-pr`, `restack-pr` and `retarget-pr`): - Select the style of the intro prepended to PR description: + Select the style of the generated section ("intro") added to the PR description: * `full` — include both a chain of upstream PRs (typically leading to `main`, `master`, `develop` etc.) and a tree of downstream PRs @@ -830,11 +832,13 @@ If `.git/info/reviewers` file is present, its contents (one GitLab login per line) are used to set reviewers. The subject of the first unique commit of the branch is used as MR title. - If `.git/info/description` or `.gitlab/merge_request_templates/Default.md` file is present, its contents are used as MR description. + If `.git/info/description` or `.gitlab/merge_request_templates/Default.md` template is present, its contents are used as MR description. Otherwise (or if `machete.gitlab.forceDescriptionFromCommitMessage` is set), MR description is taken from message body of the first unique commit of the branch. - If the newly-created MR is stacked atop another MR, the actual MR description posted to GitLab will be prepended with a section - listing the entire related chain of MRs. + If the newly-created MR is stacked atop another MR, the actual MR description posted to GitLab will include a generated section ("intro") + listing the entire related chain of MRs. This section will be delimited with `` + and `` comments in Markdown. If an MR template file exists and contains these comments already, + the generated section will be placed between them; otherwise, it will be placed at the beginning. Options: @@ -867,8 +871,8 @@ Sets the target of the current (or specified) branch's MR to upstream (parent) branch, as seen by git machete (see `git machete show up`). - If after changing the target the MR ends up stacked atop another MR, the MR description posted to GitLab will be prepended - with an intro section listing the entire related chain of MRs. + If after changing the base the MR ends up stacked atop another MR, the MR description posted to GitLab will include + a generated section ("intro") listing the entire related chain of MRs. This intro will be updated or removed accordingly with the subsequent runs of `retarget-mr`, even if the target branch is already up to date. @@ -915,7 +919,7 @@ `machete.gitlab.mrDescriptionIntroStyle` (`create-mr`, `restack-mr` and `retarget-mr`): - Select the style of the intro prepended to MR description: + Select the style of the generated section ("intro") added to the MR description: * `full` — include both a chain of upstream MRs (typically leading to `main`, `master`, `develop` etc.) and a tree of downstream MRs diff --git a/tests/test_github_create_pr.py b/tests/test_github_create_pr.py index db3ef234c..1e6b2407c 100644 --- a/tests/test_github_create_pr.py +++ b/tests/test_github_create_pr.py @@ -118,7 +118,8 @@ def test_github_create_pr(self, mocker: MockerFixture) -> None: self.repo_sandbox.write_to_file(".git/info/milestone", "42") self.repo_sandbox.write_to_file(".git/info/reviewers", "foo\n\nbar") - self.repo_sandbox.write_to_file(".github/pull_request_template.md", "# PR title\n## Summary\n## Test plan\n") + template = "# PR title\n## Summary\n## Test plan\n\n\n\n" + self.repo_sandbox.write_to_file(".github/pull_request_template.md", template) assert_success( ["github", "create-pr", "--draft"], """ @@ -155,6 +156,10 @@ def test_github_create_pr(self, mocker: MockerFixture) -> None: assert pr is not None assert pr['title'] == 'remove outdated fields' assert pr['body'] == textwrap.dedent(''' + # PR title + ## Summary + ## Test plan + # Based on PR #3 @@ -167,12 +172,7 @@ def test_github_create_pr(self, mocker: MockerFixture) -> None: * **PR #5 (THIS ONE)**: `ignore-trailing` ← `chore/fields` - - - # PR title - ## Summary - ## Test plan - ''')[1:] + ''')[1:] assert pr['draft'] is True assert pr['milestone'] == '42' assert pr['assignees'] == ['github_user'] @@ -407,8 +407,7 @@ def test_github_create_pr_for_chain_in_description(self, mocker: MockerFixture) # PR title ## Summary - ## Test plan - ''')[1:] + ## Test plan''')[1:] @staticmethod def github_api_state_for_test_create_pr_missing_base_branch_on_remote() -> MockGitHubAPIState: diff --git a/tests/test_github_retarget_pr.py b/tests/test_github_retarget_pr.py index 78ac32c6e..ea7e18d86 100644 --- a/tests/test_github_retarget_pr.py +++ b/tests/test_github_retarget_pr.py @@ -273,6 +273,7 @@ def test_github_retarget_pr_multiple_non_origin_remotes(self, mocker: MockerFixt `feature` ← `feature_1` + # Summary''')[1:] # branch feature_2 is not present in any of the remotes @@ -357,6 +358,7 @@ def test_github_retarget_pr_multiple_non_origin_remotes(self, mocker: MockerFixt `feature_2` ← `feature_3` + # Summary''')[1:] body = \ @@ -393,6 +395,7 @@ def test_github_retarget_pr_multiple_non_origin_remotes(self, mocker: MockerFixt `feature` ← `feature_3` + # Summary''')[1:] body = \ @@ -447,6 +450,7 @@ def test_github_retarget_pr_multiple_non_origin_remotes(self, mocker: MockerFixt `feature` ← `feature_4` + # Summary''')[1:] @staticmethod diff --git a/tests/test_gitlab_create_mr.py b/tests/test_gitlab_create_mr.py index 4578ea401..30e8d23af 100644 --- a/tests/test_gitlab_create_mr.py +++ b/tests/test_gitlab_create_mr.py @@ -117,7 +117,8 @@ def test_gitlab_create_mr(self, mocker: MockerFixture) -> None: self.repo_sandbox.write_to_file(".git/info/milestone", "42") self.repo_sandbox.write_to_file(".git/info/reviewers", "foo\n\nbar") - self.repo_sandbox.write_to_file(".gitlab/merge_request_templates/Default.md", "# MR title\n## Summary\n## Test plan\n") + template = "# MR title\n## Summary\n## Test plan\n\n\n\n" + self.repo_sandbox.write_to_file(".gitlab/merge_request_templates/Default.md", template) assert_success( ["gitlab", "create-mr", "--draft"], """ @@ -154,6 +155,10 @@ def test_gitlab_create_mr(self, mocker: MockerFixture) -> None: assert pr is not None assert pr['title'] == 'Draft: remove outdated fields' assert pr['description'] == textwrap.dedent(''' + # MR title + ## Summary + ## Test plan + # Based on MR !3 @@ -166,12 +171,7 @@ def test_gitlab_create_mr(self, mocker: MockerFixture) -> None: * **MR !5 (THIS ONE)**: `ignore-trailing` ← `chore/fields` - - - # MR title - ## Summary - ## Test plan - ''')[1:] + ''')[1:] assert pr['milestone_id'] == '42' assert pr['assignee_ids'] == [123456] assert pr['reviewer_ids'] == [123, 456] @@ -387,8 +387,7 @@ def test_gitlab_create_mr_for_chain_in_description(self, mocker: MockerFixture) # MR title ## Summary - ## Test plan - ''')[1:] + ## Test plan''')[1:] @staticmethod def gitlab_api_state_for_test_create_mr_missing_base_branch_on_remote() -> MockGitLabAPIState: diff --git a/tests/test_gitlab_retarget_mr.py b/tests/test_gitlab_retarget_mr.py index c85945c8a..0d218dedf 100644 --- a/tests/test_gitlab_retarget_mr.py +++ b/tests/test_gitlab_retarget_mr.py @@ -279,6 +279,7 @@ def test_gitlab_retarget_mr_multiple_non_origin_remotes(self, mocker: MockerFixt `feature` ← `feature_1` + # Summary''')[1:] # branch feature_2 is not present in any of the remotes @@ -328,7 +329,8 @@ def test_gitlab_retarget_mr_multiple_non_origin_remotes(self, mocker: MockerFixt * **MR !25 (THIS ONE)**: `feature` ← `feature_2` - ''')[1:] + + ''')[1:] # branch feature_3 present in only one remote: origin_1 and has tracking data ( @@ -375,6 +377,7 @@ def test_gitlab_retarget_mr_multiple_non_origin_remotes(self, mocker: MockerFixt `feature_2` ← `feature_3` + # Summary''')[1:] body = \ @@ -411,6 +414,7 @@ def test_gitlab_retarget_mr_multiple_non_origin_remotes(self, mocker: MockerFixt `feature` ← `feature_3` + # Summary''')[1:] body = \