Skip to content

Instantly share code, notes, and snippets.

@adam-p
Last active August 3, 2024 16:45
Show Gist options
  • Save adam-p/15413fabef6cffecd897 to your computer and use it in GitHub Desktop.
Save adam-p/15413fabef6cffecd897 to your computer and use it in GitHub Desktop.
Testing a pull request, then merging locally; and avoiding TOCTOU

It's not immediately obvious how to pull down the code for a PR and test it locally. But it's pretty easy. (This assumes you have a remote for the main repo named upstream.)

Getting the PR code

  1. Make note of the PR number. For example, Rod's latest is PR #37: Psiphon-Labs/psiphon-tunnel-core#37

  2. Fetch the PR's pseudo-branch (or bookmark or rev pointer whatever the word is), and give it a local branch name. Here we'll name it pr37:

$ git fetch upstream pull/37/head:pr37
  1. Switch to that branch:
$ git checkout pr37
  1. Compile and test.

If the PR code changes and you want to update:

# Do this while in the pr37 branch
$ git pull upstream pull/37/head

(I try to avoid pull and instead use fetch+merge, but... I don't know how to do it for this.)

Merging the PR

You can use the Github web interface, but there's a TOCTOU problem: If the pull-requester changes their master (or whatever they're PRing from) between the time you test and the time you merge, then you'll be merging code that you haven't reviewed/tested. So let's do it on the command line.

First, checkout the upstream master code:

You'll only do this the first time -- it creates the local upstream_master branch, tracks it to upstream_master, and switches to the branch:

$ git checkout -t -b upstream_master upstream/master

After the first time you'll just do:

$ git checkout upstream_master

Now merge the PR:

$ git merge pr37

NOTE: You should edit the merge commit message to reference the PR (using, say #37 in it).

Now push:

$ git push upstream HEAD:master

(You can't just git push because your local branch name is different than the remote.)

Done! Refresh the Github PR page and you'll see that the PR is now merged+closed.

@holgerbrandl
Copy link

In section "getting the PR code : (2)" is should be origin and not upstream (as in the referenced original docs

@aslafy-z
Copy link

@holgerbrandl Looks that you missed this from the intro.

(This assumes you have a remote for the main repo named upstream.)

@mlbloxer
Copy link

Thank you so much

@ANRCorleone
Copy link

ANRCorleone commented Jun 3, 2019

Thank you for this Adam :)

I have a question..when you are about to merge, do we really need a branch, which is copy of upstream master for this to work?

git checkout -t -b upstream_master upstream/master

or can we just checkout an existing master already tracked and merge the pull request on that one?

git checkout master
git merge pr37
git push

@lazarillo
Copy link

Thank you for this Adam :)

I have a question..when you are about to merge, do we really need a branch, which is copy of upstream master for this to work?

git checkout -t -b upstream_master upstream/master

or can we just checkout an existing master already tracked and merge the pull request on that one?

git checkout master
git merge pr37
git push

Yes, I also do not understand why this step is necessary. (I wanted to just upvote @AIRyndon, but it seems you cannot do that in gist.

@adam-p
Copy link
Author

adam-p commented Nov 13, 2019

@AIRyndon @lazarillo git checkout master will get you your local branch named master, which might track origin and/or might not be up-to-date, etc. The upstream_master thing is kind of hacky, but it assures me that I'm working on upstream/master.

My git-fu is not super strong and I'm happy to be corrected, though.

@kreig303
Copy link

kreig303 commented Mar 27, 2020

for the "fetch + merge" part... from memory:

% git checkout pr37
% git fetch upstream pull/37/head
% git merge upstream/pull/37/head

haven't actually tried the analogue but this should work :)

@wadkar
Copy link

wadkar commented Apr 11, 2020

for the "fetch + merge" part... from memory:

% git checkout pr37
% git fetch upstream pull/37/head
% git merge upstream/pull/37/head

haven't actually tried the analogue but this should work :)

This is the proverbial "update the PR #37 locally" piece. You can test pr37 or merge it on some other branch etc.

@mcascone
Copy link

mcascone commented Jun 5, 2020

Is it possible to use this to test a Pull Request build locally in Jenkins?
I'm not sure how the internals work, but i want to test a PR build locally, using git, without having to create the PR on my org's actual GitHub.

@Sajiyah-Salat
Copy link

I am searching for this from last 2 hours you just took 5 min to teach me... Recommended for all new GitHub maintainers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment