问题
I follow the generic OSS structure:
- the OSS' remote repository hosted on GitHub
- a fork of the OSS remote repository to my own remote repository
- a clone of the fork on my remote repository to create a local repository
Thus, a contributor would create a new branch locally, push the changes to his/her remote repository, and then open a pull request to the OSS' remote repository.
This has been working well. However, the main issue comes when I try to review another contributor's pull request by fiddling with it locally.
So I have fetched a pull request made to the OSS' remote repository using this command:
git fetch upstream pull/<PR#>/head:<branchName>
followed by git checkout <branchName>
and it was successful. I played around with the PR, and reviewed it on GitHub. Then, the contributor updated the PR by pushing new commits to their branch (on their remote repo), which was automatically reflected in the PR.
Now, I want to be able to get the updates locally so that I can try the changes again. I understand that my copy of the PR branch does not track the remote branch by default, so I tried to set it to track the PR:
git branch --set-upstream upstream/pull/<PR#>/head:<branchName>
like how I have done when I first fetched the branch. However, I got the response that
error: the requested upstream branch 'pull//head:' does not exist
I tried again with:
git branch --set-upstream-to upstream/pull/<PR#>/head:<branchName>
which also failed with the same error.
Then, I thought, is it because a PR is like a 'reflection' of the branch on someone's remote repository, so if I want to track an upstream branch I should track from the person's remote repository?
So I added the contributors' remote repository as a remote, and tried again:
git branch --set-upstream-to <newRemote> <branchName>
and I still faced the same error.
I did some Googling, and I found this, but I do not want to get all the pull requests. I also found links like this one but nope, not the help that I need there.
Can anyone point out what is wrong with the way that I am doing things now? Thanks!
Edit: Is there an easier way to do things aside from what has been proposed by Marina Liu - MSFT below?
回答1:
You can use any of below options to update the PR in local repo.
Option 1: delete the local source branch and recreate to get the update
As you use the commands to get the source branch of the PR locally:
git fetch upstream pull/<PR#>/head:<branchName>
git checkout <branchname>
If the PR is updated (new commits are pushed to the fork repo), you can delete and recreate by:
git checkout master
git branch -D <branchname>
git fetch upstream pull/<PR#>/head:<branchName>
git checkout <branchname>
Option 2: add the fork repo as a remote for your local repo
You can add the fork repo as a remote for your local repo by
git remote add fork1 <URL for the fork repo> -f
Then you can create a local branch for the PR source branch by
git checkout -b <branchname> fork1/<branchname>
If the PR has been updated, you just need to execute below commands to get the update:
git fetch fork1
git checkout <branchname> #If HEAD is not on the <branchname>
git reset --hard fork1/<branchname>
回答2:
The problem—or at least the first one—here is that you cannot use an upstream to refer to a GitHub pull request reference.
In Git, an upstream on a branch consists of two parts:
- The name of a remote, such as
origin
- The name of a branch on that remote, such as
master
Git puts these two together to get refs/heads/master
—this is the name on the remote—then runs this string through the fetch
setting(s) for the remote. The standard fetch
setting for the remote named origin
is +refs/heads/*:refs/remotes/origin/*
, so if the upstream is currently set to the pair <origin
, master
>, the name that Git looks up in your own repository is refs/remotes/origin/master
, which is your remote-tracking name for their master
.
Note the assumption in here that the name on the remote begins with refs/heads/
.
The actual name of a pull reference on GitHub begins with refs/pull/
, not refs/heads/
, so that the full name of the commit you want for pull request #123 is refs/pull/123/head
. There is no way to spell this that starts with refs/heads/
because this is not a branch name.
Now, you can—as suggested in your first link—add an extra fetch
setting:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
which causes their refs/pull/123/head
to associate with your refs/remotes/origin/pr/123
. Depending on your particular Git version, some of this sometimes or even mostly works. Some Git versions get rather confused at times. If you try it and it works for you, that's great, just be prepared to clean up a bit of a mess if you upgrade or downgrade Git versions for some reason.
The aliases found via your second link are better. These fetch from one specific pull request, creating a local branch name (or overwriting it if it already exists—this is a bit dangerous but as long as you don't name your own branches pr/integer
you will be fine). You could improve them, writing a real git-pr
script that creates a local branch—be sure to use the full name format, refs/heads/pr/number
, to guarantee correctness—and sets some additional information so that, when you are on that branch, git pr
updates the branch automatically.
(If I get some spare time, I might write my own script, because this would be pretty handy.)
来源:https://stackoverflow.com/questions/49767697/git-and-github-concepts-reviewing-updated-pull-requests-locally