2

I have a repository (origin) that has been forked (in GitHub terms) from another repository (upstream). I do all the development in topic branches and never touch the branches present in the upstream repository (master, developement, 1.x, etc.).

This is an example of the branches in my repository

$ git branch -a     # plus hand annotations
  development   [upstream-maintained: should always be == upstream/development]
  feature-1     [mine: should track origin/feature-1]
  feature-2     [mine: should track origin/feature-2]
* master        [upstream-maintained: should always be == upstream/master]
  remotes/origin/HEAD -> origin/master
  remotes/origin/development
  remotes/origin/feature-1
  remotes/origin/feature-2
  remotes/origin/master
  remotes/upstream/development
  remotes/upstream/gh-pages    [I do not care about this..]
  remotes/upstream/master
  remotes/upstream/stable-1.x  [...nor I care about these two..]
  remotes/upstream/stable-2.x  [...stable-* branches]

After I fetch from the upstream repository, I have to go through the tedious task of updating all the upstream-maintained branches: I switch to master, I merge --ff-only upstream/master and push to origin. This must be repeated for every upstream-maintained branch I care about. Please note that merge --ff-only always works because I never touch those branches.

I would like git pull to do all these tedious updates for me.

Is there a way to teach git that the upstream-maintained branches should be pushed to origin but pulled and tracked from upstream?

gioele
  • 9,748
  • 5
  • 55
  • 80
  • Are these two threads of any use?: http://stackoverflow.com/questions/4577874/git-automatically-fast-forward-all-tracking-branches-on-pull and http://stackoverflow.com/questions/4318161/can-git-pull-all-update-all-my-local-branches. Cheers! – MBlanc Jun 23 '14 at 08:27
  • @MBlanc, not really. Those questions deal with a single remote, while here I have two different remotes: one to pull from and one to push to. Thanks for the links though, the git-up tools seems nice. – gioele Jun 23 '14 at 10:26

1 Answers1

3

As mentioned in "How can I pull from one remote and push to another with git?", you can:

  • make sure to push to origin:

    git config remote.pushdefault origin
    git config push.default matching
    
  • setup the upstream branch:

    git fetch upstream
    git branch -u upstream/master foo
    

Note that you should rebase your topic branches on top of upstream/master (not merge), in order to not have merge commits in your pull requests.
That means git push -f for updating your fork remote branch (that will update the pull request automatically)

You can force a rebase either through:

git config autosetuprebase remote
# or 

git branch.foo.rebase true

For example:

C:\Users\vonc\prog\git\so>git clone https://github.com/gioele/offlineimap.git
Cloning into 'offlineimap'...
remote: Counting objects: 9445, done.
remote: Compressing objects: 100% (3701/3701), done.
remote: Total 9445 (delta 4962), reused 9445 (delta 4962)
Receiving objects: 100% (9445/9445), 5.75 MiB | 2.18 MiB/s, done.
Resolving deltas: 100% (4962/4962), done.
Checking connectivity... done.

C:\Users\vonc\prog\git\so>cd offlineimap

C:\Users\vonc\prog\git\so\offlineimap>git remote add upstream https://github.com/offlineimap/offlineimap.git

Lets see what master refers to for now:

C:\Users\vonc\prog\git\so\offlineimap>git branch -avvv
* master                  1746676 [origin/master] Make IDLE mode to work again
  remotes/origin/HEAD     -> origin/master

C:\Users\vonc\prog\git\so\offlineimap>git config --local -l
remote.origin.url=https://github.com/gioele/offlineimap.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
remote.upstream.url=https://github.com/offlineimap/offlineimap.git
remote.upstream.fetch=+refs/heads/*:refs/remotes/upstream/*

Let's make origin as the destination for a push:

C:\Users\vonc\prog\git\so\offlineimap>git config push.default matching
C:\Users\vonc\prog\git\so\offlineimap>git config remote.pushdefault origin

Let's change the upstream branch:

C:\Users\vonc\prog\git\so\offlineimap>git fetch upstream
remote: Counting objects: 55, done.
remote: Compressing objects: 100% (55/55), done.
remote: Total 55 (delta 25), reused 1 (delta 0)
Unpacking objects: 100% (55/55), done.
From https://github.com/offlineimap/offlineimap
 * [new branch]      master     -> upstream/master

C:\Users\vonc\prog\git\so\offlineimap>git branch -u upstream/master master
Branch master set up to track remote branch master from upstream.

The master branch is set as monitoring upstream/master:

C:\Users\vonc\prog\git\so\offlineimap>git br -avvv
* master                    1746676 [upstream/master: behind 10] Make IDLE mode to work again

Now a git pull (or better, a git pull --rebase) will pull from upstream:

C:\Users\vonc\prog\git\so\offlineimap>git pull --rebase
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 6bd76fed5a7e1e24310517b3510c465929870c08.

(and 6bd76fed5a7e1e24310517b3510c465929870c08 was upstream/master commit)

A git push would still push to origin:

C:\Users\vonc\prog\git\so\offlineimap>git push
remote: Permission to gioele/offlineimap.git denied to VonC.
fatal: unable to access 'https://github.com/gioele/offlineimap.git/': The requested URL returned error: 403

(normal, since I am not gioele, I don't have write access to that repo)

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Shouldn't the branches in the first command be swapped? `git branch -u upstream/master master` – gioele Jun 23 '14 at 10:07
  • Also, once I use `git config branch.master.remote origin`, `git push` refuses to push anything because "Everything is up-to-day" while upstream has two more commits. – gioele Jun 23 '14 at 10:10
  • @gioele if you don't pull/rebase first, then yes, a push would do nothing. – VonC Jun 23 '14 at 11:23
  • I tried again and did a pull first and it did not work. You can try using the current situation at https://github.com/gioele/offlineimap.git as `origin` and https://github.com/offlineimap/offlineimap.git as `upstream`. branch `master` and `next` are upstream-maintained and will not be pulled/pushed using your configuration. – gioele Jun 25 '14 at 18:39
  • @gioele I have fixed the exact sequence of commands to apply, and make a complete example out of your two repos: it works just fine. – VonC Jun 25 '14 at 20:11
  • yes, now everything is working as intended. Thank you. – gioele Jun 26 '14 at 06:39