Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@lucasmelin
Copy link
Contributor

Fixes #6034

Adds a new pr revert command that enables reverting a merged PR using the gh CLI.

Usage

# Revert a PR
$ gh pr revert 123

# Provide revert PR options
$ gh pr revert --draft --title 'Example title' --body 'Example body' 123

@lucasmelin lucasmelin requested a review from a team as a code owner March 17, 2024 03:43
@lucasmelin lucasmelin requested review from williammartin and removed request for a team March 17, 2024 03:43
@cliAutomation cliAutomation added the external pull request originating outside of the CLI core team label Mar 17, 2024
@lucasmelin
Copy link
Contributor Author

Putting back into draft to add the revert PR details to the success message output.

@lucasmelin lucasmelin marked this pull request as draft March 17, 2024 13:06
@lucasmelin
Copy link
Contributor Author

Added the revert PR details to the message output, ready for review.

@lucasmelin lucasmelin marked this pull request as ready for review March 17, 2024 13:28
Copilot AI review requested due to automatic review settings July 27, 2025 16:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a new gh pr revert command that allows users to revert merged pull requests using the GitHub CLI. The feature supports customization of the revert PR with options for title, body, and draft status.

  • Adds core revert functionality with validation to ensure only merged PRs can be reverted
  • Includes comprehensive test coverage for successful reverts, error cases, and option handling
  • Integrates the new command into the existing PR command structure

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
pkg/cmd/pr/revert/revert.go Core implementation of the revert command with options handling and API integration
pkg/cmd/pr/revert/revert_test.go Comprehensive test suite covering success cases, error handling, and option validation
pkg/cmd/pr/pr.go Integration of the revert command into the main PR command structure
api/queries_pr.go GraphQL API function for executing pull request revert mutations

@BagToad
Copy link
Member

BagToad commented Sep 25, 2025

πŸ‘‹ Hi @lucasmelin! I just posted the Acceptance Criteria for this issue in #6034 (comment). I also added the help wanted label, so this is now ready for community contributions per our contributing guidelines 😁

It looks like there's some tests failing - please let me know if you're still interested in contributing to this! Please also let me know if you have any questions about the Acceptance Criteria or anything else πŸ˜ƒ

cc @connor15mcc since you commented on the issue as well.

@lucasmelin lucasmelin requested review from a team as code owners October 6, 2025 16:58
@lucasmelin lucasmelin force-pushed the lucasmelin/add-pr-revert-command branch from 912fcfe to ef7ac8c Compare October 6, 2025 17:29
Copy link
Member

@BagToad BagToad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @lucasmelin πŸ‘‹ Doing some testing with this, and it's looking good! While testing, I noticed some type errors when we use the full PullRequest type:

❯ gh pr revert 75
X GraphQL: Field 'id' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.autoMergeRequest.enabledBy.id), Field 'name' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.autoMergeRequest.enabledBy.name), Field 'id' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.author.id), Field 'name' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.author.name), Field 'id' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.mergedBy.id), Field 'name' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.mergedBy.name), Field 'name' doesn't exist on type 'RepositoryOwner' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.headRepositoryOwner.name), Field 'nodes' doesn't exist on type 'StatusCheckRollup' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.statusCheckRollup.nodes), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.id), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.login), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.name), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.typeName), Field 'status' doesn't exist on type 'ProjectV2Item' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.projectItems.nodes.status), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.typeName), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.login), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.name), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.slug), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.organization)
API call failed: GraphQL: Field 'id' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.autoMergeRequest.enabledBy.id), Field 'name' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.autoMergeRequest.enabledBy.name), Field 'id' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.author.id), Field 'name' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.author.name), Field 'id' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.mergedBy.id), Field 'name' doesn't exist on type 'Actor' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.mergedBy.name), Field 'name' doesn't exist on type 'RepositoryOwner' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.headRepositoryOwner.name), Field 'nodes' doesn't exist on type 'StatusCheckRollup' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.statusCheckRollup.nodes), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.id), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.login), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.name), Selections can't be made directly on unions (see selections on Assignee) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.assignedActors.nodes.typeName), Field 'status' doesn't exist on type 'ProjectV2Item' (mutation PullRequestRevert.revertPullRequest.revertPullRequest.projectItems.nodes.status), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.typeName), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.login), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.name), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.slug), Selections can't be made directly on unions (see selections on RequestedReviewer) (mutation PullRequestRevert.revertPullRequest.revertPullRequest.reviewRequests.nodes.requestedReviewer.organization)

To solve this, I think we should do something similar to what the create pull request mutation does and return just the basic pull request info. Here's a diff of the change I think we need:

diff --git a/api/queries_pr.go b/api/queries_pr.go
index c34c9a80c..0eb8441ed 100644
--- a/api/queries_pr.go
+++ b/api/queries_pr.go
@@ -770,7 +770,11 @@ func PullRequestRevert(client *Client, repo ghrepo.Interface, params githubv4.Re
 			PullRequest struct {
 				ID githubv4.ID
 			}
-			RevertPullRequest PullRequest
+			RevertPullRequest struct {
+				ID     string
+				Number int
+				URL    string
+			}
 		} `graphql:"revertPullRequest(input: $input)"`
 	}
 
@@ -781,7 +785,12 @@ func PullRequestRevert(client *Client, repo ghrepo.Interface, params githubv4.Re
 	if err != nil {
 		return nil, err
 	}
-	revertPR := &mutation.RevertPullRequest.RevertPullRequest
+	pr := &mutation.RevertPullRequest.RevertPullRequest
+	revertPR := &PullRequest{
+		ID:     pr.ID,
+		Number: pr.Number,
+		URL:    pr.URL,
+	}
 	return revertPR, nil
 }

What do you think?

@cmbrose cmbrose removed the request for review from a team October 22, 2025 20:03
@lucasmelin lucasmelin force-pushed the lucasmelin/add-pr-revert-command branch from 941efb6 to 6db1441 Compare October 22, 2025 22:02
@lucasmelin
Copy link
Contributor Author

@BagToad, makes sense. πŸ‘πŸ» Implemented your suggestion in the most recent commit.

Copy link
Member

@BagToad BagToad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your patience @lucasmelin πŸ™

I've tested this and reviewed the code and it looks good to me πŸ‘ Thank you for this contribution!

@BagToad BagToad merged commit b90e39e into cli:trunk Oct 23, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external pull request originating outside of the CLI core team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide gh cli Support to Revert Pull Request

3 participants