48

When you fork a repository on github your forked repo contains all branches and tags.

Over time these branches and tags gets outdated.

How does one as easy it is with fork make sure your fork has all branches and tags without having to reclone ?

i.e. a git magicpull --rebase upstream/* myremote/*

which would fetch all the branches and tags in upstream and make sure the same are present in myremote.

Max Rydahl Andersen
  • 2,819
  • 2
  • 19
  • 23

4 Answers4

48

This assumes your "upstream" remote is named "origin" and you have your custom fork under your username (i.e. "maxandersen")

When you have your clone run the following one-liner (refresh of Track all remote git branches as local branches :

remote=origin ; for brname in `git branch -r | grep origin | grep -v master | grep -v HEAD | sed -e 's/.*\///g'`; do git branch --track $brname  $remote/$brname ; done

This will setup tracking branches for all the branches found in the remote named 'origin'. If you already have a checkout with this branchname it will not change anything except ensure the tracking is in place.

(Optional) Now ensure all your branches are uptodate (useful if you have already branches checked out):

git pull --rebase --all

Now with all branches setup for tracking and uptodate push branches and tags to your remote (replace 'maxandersen' with your remote name):

git push --all maxandersen
git push --tags maxandersen

After this your fork is in sync.

The following script does all this including asking for confirmation:

## Checkout all branches from remote as tracking branches. Based on    https://stackoverflow.com/questions/379081/track-all-remote-git-branches-as-local-branches/6300386#6300386

UPSTREAM=$1
MYREPO=$2

usage() {
   echo "Usage:"
   echo "$0 <upstream-remote> <target-remote>"
   echo ""
   echo "Example which ensures remote named 'maxandersen' have all the same branches and tags as 'origin'"
   echo "$0 origin maxandersen"
   exit 1
}

if [ -z "$UPSTREAM" ]
then
 echo Missing upstream remote name.
 usage
fi

if [ -z "$MYREPO" ]
then
 echo Missing target remote name. 
 usage
fi

read -p "1. This will setup '$MYREPO' to track all branches in '$UPSTREAM' - Are you sure ?" -n 1 -r

if [[ $REPLY =~ ^[Yy]$ ]]
then
 for brname in `git branch -r | grep "$UPSTREAM" | grep -v master | grep -v HEAD | sed -e 's/.*\///g'`; do git branch --track $brname  $UPSTREAM/$brname ; done
fi

read -p "2. This will push all local branches and tags into '$MYREPO' - Are you sure ?" -n 1 -r

if [[ $REPLY =~ ^[Yy]$ ]]
then
 git push --all $MYREPO
 git push --tags $MYREPO
fi

Save it as 'updateallbranchestags.sh' and execute it with:

sh updateallbranches.sh origin maxandersen

And all branches/tags from 'origin' will be made available in remote named 'maxandersen'

Community
  • 1
  • 1
Max Rydahl Andersen
  • 2,819
  • 2
  • 19
  • 23
  • Sound a concrete implementation of my answer. +1 – VonC Apr 03 '13 at 07:30
  • 1
    Yes, note that I also move to use --track instead of --set-upstream to get rid of annoying deprecation warning + I used sed instead of awk to make the oneliner even shorter :) Thus thank you for the hints! – Max Rydahl Andersen Apr 03 '13 at 07:36
  • I would not recommend --track for reason explained in my one-liner answer http://stackoverflow.com/a/6300386/6309 (updated): you should use `--set-upstream-to` (or `-u`), as explain in http://stackoverflow.com/a/10002469/6309 – VonC Apr 03 '13 at 07:41
  • 1
    thanks - didn't realize that subtle difference. answer updated. – Max Rydahl Andersen Apr 03 '13 at 09:34
  • Interesting. I didn't know `--set-upstream-to` didn't work in this case. I will keep that in mind. – VonC Apr 06 '13 at 09:38
  • 2
    very nice, I would adjust the sed expression to avoid stripping away parts of branch names with slashes in: `'s/^[^\/]*\///'` – derke Dec 07 '16 at 16:47
  • Any way to do this in powershell? – Mladen Mihajlovic Dec 24 '16 at 08:43
20

You would still need a local clone, which would:

upstream and fork

  • git push --all origin (origin being your fork): that supposes that:
    • you have all the local branches tracking all the upstream branches (see previous step).
      Otherwise, you would push only one local branch by default, since a clone would create only one local branch (the default one)
    • you haven't pushed commits of your own on those branches.
Community
  • 1
  • 1
VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
4

You can directly push the remote refs. Obviously this doesn't take into account changes in the fork, But it still answers the question. And if the changes are limited then you can easily merge/rebase them using your local branches.

git push -f origin refs/remotes/upstream/*:refs/heads/*
Tamir Daniely
  • 1,513
  • 1
  • 18
  • 24
-2

Here https://asciinema.org/a/lv9v5mh1GGQJsfKIzUSlzsg7i is a no huzz-fuzz actual demo how I sync my cloned repo's master and release-18.09 branches from upstream.

eigenfield
  • 2,331
  • 1
  • 22
  • 23
  • Having to watch several Minutes to see that you seem to be doing a manual longer version of the things explained above isn’t great. Hence the downvote. – Max Rydahl Andersen Oct 28 '18 at 10:04