Most projects on GitHub have a main repository that's the focal point of activity. For example, the Example organization has the Example.com repository:
https://github.com/example/example.com
Developers of Example.com typically call this the 'upstream' repository. We'll come back to it in a moment.
Using GitHub, each individual developer of Example.com uses the Fork button to create his or her own GitHub-hosted copy of the Example.com repository. For example, Alice forks the repository to her account:
https://github.com/alice/example.com
Using standard Git terminology, this is Alice's remote 'origin'
repository. She can create a copy of it on her local computer using the
git clone
command:
git clone https://github.com/alice/example.com.git
Changing directory into her local repository, she can now add to her remote list the upstream repository and fetch data from it:
cd example.com
git remote add upstream https://github.com/example/example.com
git fetch --all
To edit a file, Alice checks out a new branch based off of the upstream repository (not her own), edits the file, commits her change, and pushes it to her remote origin.
git checkout -b new_branch upstream/master
$EDITOR the_file
git commit -a -m 'Edited The File'
git push origin new_branch
From the GitHub user interface, she can now open a Pull Request (PR). Her PR number is #123.
Bob discovers a bug in Alice's PR#123. Rather than trying to explain it, he wants to send Alice a patch using GitHub. He has already setup his own fork on GitHub, cloned it, and added a remote upstream. He just needs a local copy of Alice's code.
He could add Alice's repository as a remote, but he'd need to do that for each new contributor to Example.com. Instead, he wants to use GitHub's special pull references to access Alice's code directly. Bob changes directory to his local repository and opens his Git configuration file for editing:
cd example.com
$EDITOR .git/config
Then he adds the following lines to the bottom of the file:
[remote "upstream-pull"]
url = https://github.com/example/example.com.git
fetch = +refs/pull/*:refs/remotes/upstream-pull/*
After saving and closing the file, he pulls in the references for his new 'upstream-pull' remote:
git fetch --all
Bob can now checkout a new branch based on Alice's PR#123, fix the bug, commit his changes, and push them to his origin:
git checkout -b fix-the-file upstream-pull/123/head
$EDITOR the_file
git commit -a -m 'Fixed a bug'
git push origin fix-the-file
Finally, Bob can open a pull request against Alice's new_branch
.
Unfortunately, GitHub isn't smart enough yet to guess what branch you
want to patch, so Bob's best bet is to browse to Alice's origin and open
the PR from there:
https://github.com/alice/example.com
Bob's PR is assigned the number #7 in Alice's repository.
Alice is notified of Bob's PR#7, but she wants to test it locally.
Unfortunately, she can't use the upstream-pull trick directly because it
only applies to PRs made to the upstream repository---but she can modify
it to work for her repository. Editing her own .git/config
, Alice
adds the following lines:
[remote "origin-pull"]
url = https://github.com/alice/example.com.git
fetch = +refs/pull/*:refs/remotes/origin-pull/*
She then fetches the refs and then locally-only merges PR#7 into her
new_branch
for testing.
git fetch --all
git checkout new_branch
git merge origin-pull/7/head
After testing, Alice is satisfied and pushes the updated branch to her origin, which automatically updates her PR#123 and marks as merged Bob's PR#7:
git push origin new_branch
You need to run git fetch --all
or an equivalent command to get the
most recent data from all of your remotes. For example, if someone opens
PR#8 on the Alice's repository, Alice won't be able to see it until
she runs fetch.
This can cause confusion when remote branches are updated, so it is recommended to always run fetch immediately before running commands like checkout and merge using a remote.
In this document, we showed you how to:
-
Create an 'origin' remote pointing to your GitHub fork by using
git clone
-
Create an 'upstream' remote pointing to a project main repository
-
Create an 'upstream-pull' remote containing a branch for every PR in the upstream repository
-
Create an 'origin-pull' remote containing a branch for every PR to your own repository
In addition to enabling the process above, it is convenient to use the upstream-pull remote to make signed merges on the command line:
git checkout master
git pull
git merge -S upstream-pull/123/head
git diff upstream/master
git push upstream master
Thanks goes to Pieter Wuille for describing the -pull remote trick.
Thank you for explaining the above concept so clearly. I understand it much better now. I am new to git, so may be this would be silly question . Bob is another developer or owner/maintainer of the repository who have access to accept the changes.