Arnold Rimmer
Arnold Rimmer

Reputation: 3111

How do I checkout a PR from a fork?

I'm using GitHub to host some projects and someone forked my repo and submitted a PR. I have never had to test a PR in a fork before. How can I checkout the branch and test it? Can I some how pull it into my repo? Or do I checkout the fork and test the branch that way?

Upvotes: 32

Views: 15112

Answers (9)

Hippolyte BRINGER
Hippolyte BRINGER

Reputation: 863

For Bitbucket

You need to replace the word pull with pull-requests.

First, you can display the name of the pull request in progress thanks to:

$ git ls-remote origin
037edad0925814a92b60a48ee3e36bf64e1df118        refs/heads/pylint
9f27ad743908b25ef3ddfbf8eb95db7de898eb37        refs/pull-requests/1/from

As you can see, it is refs/pull-requests/1/from:my_new_branch instead of refs/pull/1/from:my_new_branch

So:

git fetch origin refs/pull-requests/1/from:my_new_branch
git checkout my_new_branch

Upvotes: 1

Ryan H
Ryan H

Reputation: 1746

Since you're using GitHub, my preferred way to do this is using the official GitHub CLI.

https://github.com/cli/cli

Using the GitHub CLI, you can execute

gh pr checkout 101

to checkout pr #101

There's also a lot of other useful commands regarding pull requests in the CLI.

Upvotes: 6

Doug
Doug

Reputation: 2610

GitHub includes instructions in the pull request for doing this from the command line: Screenshot of GitHub PR showing link to view command line instructions

Clicking the "command line instructions" link shows the following:

git checkout -b [new-local-branch-name] main
git pull [email protected]:[remote]/[forked-repo].git [the-original/forked-branch-name]

Upvotes: 3

jschmitter
jschmitter

Reputation: 1939

You don't need access to the fork. Just fetch it from the main repo using the PR ref. If this is PR 3, then fetch pull/3/head like this:

git fetch origin pull/3/head:my_new_branch
git checkout my_new_branch

Upvotes: 31

adamjarling
adamjarling

Reputation: 81

My scenario (close if not identical to yours) is maintaining a Github repo which others have forked, and submit PRs. Here's my process for reviewing forked PRs:

git remote add <forked-repo-org-or-name> <forked-repo-github-url>

Check the remote was added:

git remote -v

Fetch the forked repo for latest updates:

git fetch <forked-repo-org-or-name>

Checkout the forked PR branch:

git checkout <name-of-pr-branch>

Now you can locally test the branch, explore, and decide whether to merge, comment, etc.

Upvotes: 5

Matt Robinson
Matt Robinson

Reputation: 897

Specific answer for clean CI machine minimal checkouts that can work for Github PRs with a source branch from forks or not.

First, some environment variables for clarity:

# This is likely provided by the CI provider. Just the normal clone URL.
GIT_HTTP_URL = "[email protected]:organization/repo.git"
# This is the pull request number. Example: https://github.com/organization/repo/pull/14726
PULL_REQUEST_ID = 14726

Command to run for sparse checkout of PR:

$ git init
$ git remote add origin $GIT_HTTP_URL
$ git fetch --jobs=10 --no-tags --depth=1 origin "refs/pull/$PULL_REQUEST_ID/head:pull/$PULL_REQUEST_ID"
$ git checkout "pull/$PULL_REQUEST_ID"

This takes the PR checkout time (for my fairly large example repo) from ~1 minute to ~10 seconds.

Upvotes: 1

ErikMD
ErikMD

Reputation: 14743

Basically the "upstream" GitHub repository provides direct access to the forks' PR branches (in read-only) so that you can fetch a given PR and test the corresponding code after specifying the appropriate ref, pull/ID/head.

To this aim, I often use the following alias (which can be used for both initial fetch, then subsequent fetches if the PR has been updated−thereby overwriting the pr/ID local branch):

$ git pr
Usage: git pr <id> [<remote>]  # assuming <remote>[=origin] is on GitHub

$ git pr 101  # fetch PR #101 from origin -> branch pr/101

$ git pr 101 upstream # fetch PR #101 from upstream -> branch pr/101

Disclaimer: this definition is not the very last version of the command, see Further automation below.

Here is the one-liner definition, then an expanded form:

$ git config --global alias.pr '!f() { if [ $# -lt 1 ]; then echo "Usage: git pr <id> [<remote>]  # assuming <remote>[=origin] is on GitHub"; else git checkout -q "$(git rev-parse --verify HEAD)" && git fetch -fv "${2:-origin}" pull/"$1"/head:pr/"$1" && git checkout pr/"$1"; fi; }; f'

# git config --global alias.pr '!f() { if [ $# -lt 1 ]; then
  echo "Usage: git pr <id> [<remote>] # assuming <remote>[=origin] is on GitHub";
  else git checkout -q "$(git rev-parse --verify HEAD)" &&
  git fetch -fv "${2:-origin}" pull/"$1"/head:pr/"$1" &&
  git checkout pr/"$1";
  fi; }; f'

Note however that you cannot directly push to these special branches.

If ever you'd like to directly modify the PR (commit+force-push) as a maintainer, you should then add the fork as another remote, as suggested by @yes-siz (provided the PR author authorized such access when opening their PR).

Further automation

It can be noted that the git pr alias above creates a read-only branch, because being able to force-push to the branch that is associated with the PR would require to push to a specific branch within the source fork repository (assuming its owner authorized this access, as mentioned previously).

Fortunately, GitHub's REST API allows one to easily retrieve this information (the GitHub source repository as well as the source ref), so that one can automate this by relying on a simple curl call and a few standard Git commands including git branch --set-upstream-to.

All things put together, we can obtain some handy Bash command:

$ git prw

Facility to fetch a read/write branch from a GitHub repo Pull Request.

Usage:
  git prw <ID> [<REMOTE>] [-f]

Example:
  git prw 390 upstream

Summary:
  If the REMOTE argument is omitted, it defaults to "origin".
  REMOTE must point to a GitHub repository.

  This command checkouts the branch named "pr/ID" (if it doesn't exist
  yet, it fetches the source branch for the PR #ID in the REMOTE repo)
  and sets its upstream branch so that one can force-push to the fork
  (using an SSH URL); it reuses (if applicable) an existing remote
  matching that URL, or creates a remote named REMOTE-fork-for-pr-ID.

  Flag -f overwrites the local branch pr/ID even if it already exists.
  In general, it is a good idea to pass flag -f, unless we already ran
  "git pr ID REMOTE" and did commits in the local branch pr/ID.

  It requires curl <https://curl.se/> and (optionally) jq.

See also:
  - https://stackoverflow.com/a/62432946/9164010
  - https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/checking-out-pull-requests-locally
  - https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork

I published this git-prw command in my git-scripts GitHub repository (given it is not a one-liner script any longer :) and this repository also contains an up-to-date version of the git-pr command.

Upvotes: 12

yes-siz
yes-siz

Reputation: 398

There are a couple different ways but I’ll go over what I would do in this situation

git remote add <whatever you want the remote to be called> <link to the fork>

Here is the documentation. This will allow you to add and check out the remote branch from the fork. When reviewing PRs in the workflow you described I usually do a git clean -dfx (warning: this is a very intensive clean that gets rid of unstaged work you have), git remote add <whatever you want the remote to be called> <link to the fork>, and git checkout <branch name>.

If it’s in your repo already you can see that with git branch -a and simply check it out as you might otherwise.

Upvotes: 2

matt
matt

Reputation: 535617

The PR is in your repo. That's the whole point of the fork-and-PR architecture.

So just git fetch and take a look however you like on your machine.

But when the time comes to merge, then yes, you will pull the branch from the fork. Fortunately you can have GitHub do that for you.

Upvotes: 0

Related Questions