the workflow we are required to follow is this:
That git remote add upstream …
sequence of commands is the correct way to get a local copy of the original repo’s master
branch.
This implies that your local cloned repo has 2 parents – the original repo and your forked repo. How can this work? How can you fetch from two different repos into one repo?
Git call them “remotes” rather than “parents”. Yes, your repository will have two remotes (links to remote repositories) after this operation.
When you git clone
your local repo from your fork, your local repo automatically gets one remote called origin
, and automatically creates a local branch master
based on the remote branch origin/master
. There should be no need to manually git remote add origin
because the origin
remote is created by default, but it wouldn’t hurt. Then the git remote add upstream …
command adds a second remote called upstream
.
There is no ambiguity when you have multiple remotes, because GitHub namespaces all branches from each remote with name/
at the beginning. The master
branch on your forked origin
remote is referred to as origin/master
, and the master
branch on the original upstream
remote is referred to as upstream/master
. If you refer to a branch with no namespace, such as master
, this refers to a branch in your local repo.
You can see the list of all branches stored in your Git repo with git branch --list -a
. This includes local-only branches such as master
as wells as local backups of remote branches like origin/master
and upstream/master
. Your repo's local backups of the remote branches will be updated when you run git fetch --all
(or git fetch --all --prune
, which deletes local backups of branches that were deleted on that remote).
Presumably, the forked repo will never know about the updates pulled from the original repo?
If you want to update one remote based on another remote, you always have to do it through a branch in your local repo. You can’t directly push or pull between remotes.
First, to make sure you have the latest commits from all remotes, run git fetch --all
, as mentioned previously.
Now that the original repo’s master
is accessible at upstream/master
, you can merge it into your local master
branch. Do this with git checkout master
followed by one of git merge upstream/master
or git rebase upstream/master
. After this, you can git push origin master
to push your local master
branch’s commits into origin/master
.
If you wanted to create a new branch on your forked origin
repo that matches the upstream
’s master
branch, you can git branch upstream-master upstream/master
to create a local upstream-master
branch, then git push origin upstream-master
to push a new branch upstream-master
to your origin
remote. You could also rename the branch during the push by using a :
, like in git push origin upstream-master:old-master
.
As the other answer describes, there is nothing wrong in having 2 remotes. Actually, to submit feature branches, you do not have to perform any re-syncing or your fork. You need to follow so-called triangular workflow (search there for "Improved support for triangular workflows").
tl:dr:
<fork in Web>
git clone <URL>
cd clone
git add upstream <upstream URL>
<later>
git fetch upstream
git checkout -b <feature> upstream/master
<develop, commit>
git push origin <feature>
<make PR in Web>
As you can see, you only update here the <feature>
branch of your fork, which is up-to-date with upstream - just the one you need to submit a PR. Basically, the whole purpose for the fork to exist is to have that one branch, then there is no reason to maintain other branches in the fork.
The question Best practice for tracking upstream in fork on github goes beyond that, it needs to "tracking of changes unique to the fork". When such goal arises then there is a task of maintaining those changes up-to-date, but not before.