git - Tracking Different Remotes on Different Branches

A friend of mine has a git repository I'm using extensively: https://github.com/vonbrownie/grubs . Checking this out is easy: git clone git@github.com:vonbrownie/grubs.git. But what I really wanted was to have a branch of my own so I could save my changes. Given the nature of his repository, my changes (mostly the grub.cfg) weren't things he was going to pull. So I wanted to back up my work to my own remote repository. I managed that ... but I unfortunately didn't remove his version of the repository from my remote, so now I have a slowly aging copy of his master attached to my own branch. Still, it mostly works. The problem I have now is that if I check out my version of the repo, 'master' points to my old copy of 'master' on my remote when I want it to track his version.

I love git, but it's also fantastically complex. There's justification for that - because it's capable of handling thousands of people with millions of branches and remotes. But that power comes with some pretty horrible complexity in the settings. I don't find this stuff obvious, so I wanted to make some notes about it.

So we start again, checking out my version of the two-branched repository:

$ git clone gituser@myserver.com:~/ggrubs.git
...
$ cd ggrubs
$ git remote -v
origin  gituser@myserver.com:~/ggrubs.git (fetch)
origin  gituser@myserver.com:~/ggrubs.git (push)
$ git remote add daniel git@github.com:vonbrownie/grubs.git
$ git remote -v
daniel  git@github.com:vonbrownie/grubs.git (fetch)
daniel  git@github.com:vonbrownie/grubs.git (push)
origin  gituser@myserver.com:~/ggrubs.git (fetch)
origin  gituser@myserver.com:~/ggrubs.git (push)

I've added another remote ... but it doesn't do much yet. To know what's going on, we need to know which branch tracks what remotes. This turns out to not have an obvious command associated with it, but StackOverflow to the rescue:

$ git branch -vv
* giles 95dc129 [origin/giles] Broke the config last time (no closing '}').  Also updating new Alpine ... doesn't work.

Let's add master:

$ git checkout master
Branch master set up to track remote branch master from origin.
Switched to a new branch 'master'
$ git branch -vv
  giles  95dc129 [origin/giles] Broke the config last time (no closing '}').  Also updating new Alpine ... doesn't work.
* master 03bd171 [origin/master] save

So we have a master, but it still points to my remote origin (reasonably enough). This can be made to work:

$ git pull daniel master
...

That did the right thing. And many people are happy with this four word invocation, but I find the opportunities for error are huge: if you forget which branch you have checked out, or choose the wrong remote, it's very easy to break things. So I prefer to set defaults:

$ git branch -u daniel/master
Branch master set up to track remote branch master from daniel.
$ git branch -vv
  giles  95dc129 [origin/giles] Broke the config last time (no closing '}').  Also updating new Alpine ... doesn't work.
* master 4bdad7e [daniel/master] /boot/grub[2] test

So finally I have what I want: I can type git push or git pull in the branch I'm in and it will "do the right thing" - even though "the right thing" is two different remotes.

This also means that I can occasionally merge his work into my branch so my version doesn't go stale. I could theoretically push his changes up to my remote ggrubs/master so that version gets updated ... I'll think about it.

Extra Points

git push -u <remote> <local_branch> also works. This implies git pull -u ... but the man page says that's an entirely different command. Does git push -u daniel master do the same thing as git branch -u daniel/master? I'm too tired of repeatedly cloning and mangling my directory to find out right now.