Git Upstreams & Submodules
Upstreams
Sometimes you may encounter such a situation. You want to fork some projects and stay updated to those projects, but in the meantime you want to do some personal modifications. However, you don’t want to send those personal changes back to those upstreams (e.g those changes contain your personal information) and you want to make your forked repositories private (but you can’t with forking). Now all you need is git upstreams.
To make things simply, let’s say there is one repository on github called A
, the first thing you wanna do is create a new empty repository B
in your github, record the <urlB>
of your repo. Then clone repo A
to your local machine as usual:
$ git clone <urlA> repoName
$ cd repoName
Make the origin of this repoName
upstream:
$ git remote rename origin upstream
Use your <urlB>
and add your repoName
to this url:
$ git remote add origin <urlB>
Then you can push changes back to your repo B
:
$ git push origin master
Till now, you successfully make A
as upstream and B
as the origin. Next time you want to update your B
to A
, all you need to do is:
$ git pull upstream master && git push origin master
Deal with those conflicts (if any) and then your private repo B
is up to date with A
but also have your own modifications as well.
Submodules
Now let’s say you actually have a larger project C
of which the B
above is a part. In other words, you have two remote repos C
and B
and you want B
updated with A
as mentioned above. So B
is in fact a submodule under C
. This will cause some new issues, in fact. If you do nothing and try git commit
the changes of B
under C
you will encounter warnings (Changes not staged for commit
) and the changes are actually not commited. To solve this, you need to make B
as submodule of C
and pull/push two repos independently.
$ cd /path/to/local/B
$ git submodule add <urlB>
A common practice is when you finish your changes to B
and C
, go to the path of B
and push those changes to repoB first:
$ cd /path/to/local/B
$ git add .
$ git commit -m "commitMsg"
$ git push origin master
Then go back to the root of C
and push changes:
$ cd /path/to/local/C
$ git add .
$ git commit -m "commitMsg"
$ git push origin master
If you have multiple submodules and you want to push changes of everything at one time (normally I don’t do it this way), you may want to take a look here.