John Little
John Little

Reputation: 12437

git: how to re-syc a fork?

the workflow we are required to follow is this:

  1. fork a project on github into your own private githib account.
  2. clone forked project to local machine.
  3. create feature branch (of master) on local machine.
  4. commit branch to forked repo.
  5. do a pull request on the main repo to the new branch on the forked repo.

This is great, but a few days later we need to create a new feature branch. In the mean time some features have been commited to master on the main repo.

If we now create a new branch on our repo, push it to our forked copy, we are working with old out of date code.

So how do we pull the latest master from the original repo we dont have permission on, into our forked repo, then down to our local repo?

Or is it best to always create a new fork for each feature branch, and try to work quickly (as the code will soon be out of date as we cant pull in changes pushed by others).

This has some discussion on the subject:

Best practice for tracking upstream in fork on github

But is missing what I need, which is how to do this with actual git commands.

E.g. what we have now is this:

  1. fork on github to local repo using github web ui
  2. git clone https://github.com/myname/aproject
  3. git remote add origin https://github.com/myname/aproject # not sure why we have to do this.
  4. git checkout -b mybranch
  5. do some work.
  6. git commit -m ...
  7. git push origin mybranch # puts the new branch on our personal github forked copy
  8. make a pull request via github ui.

What we dont know is what commands we would need to get the latest master updates from the original github repo, through to our forked copy of that repo on in our private github account, then finally down to our local cloned copy of the forked repo.

E.g. how would we tell the github hoasted forked repo to update itself from the repo it was forked from?

Or, if this is not possible, a way to pull the latest master from the original github hosted repo directly to the local cloned copy on the developers PC (bypassing the forked repo in the devs. private github account)

I also saw this post:

How do I update a GitHub forked repository?

The accepted answer is this:

git remote add upstream https://github.com/whoever/whatever.git
git fetch upstream
git checkout master
git rebase upstream/master
  1. How does the fork get the new master updates? This updates the master of your local repo only?
  2. 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? Presumably, the forked repo will never know about the updates pulled from the original repo? When you next push a second feature branch back to your forked repo, it will be based on the wrong code, so the forked repo will be differnt to your local repo, and tests which work locally would not work if you re-checked out everything from your forked repo to a fresh dir?

Upvotes: 0

Views: 379

Answers (2)

max630
max630

Reputation: 9248

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.

Upvotes: 2

Rory O&#39;Kane
Rory O&#39;Kane

Reputation: 30408

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.

Upvotes: 1

Related Questions