If you don't mind having multiple roots, you can do this (per sub-project):
- go into the sub-project - we'll call it project 'foo'
- make a 'foo' folder in there (we want everything contained by project name)
git mv
everything at the root into that root 'foo' folder
- commit the changes
Now in the master project (presuming you want to merge both 'master' branches):
git remote add foo /path/to/foo/project
git fetch foo
- from the master project's master branch do
git merge foo:master
This will create a merge commit, and from that point on you'll have everything from the foo sub-project in a 'foo' folder in the master project. Before that merge point you'll be on either of the two separate trees. It doesn't make sense for their histories to intermingle, so this is a fine way to set things up, wherein the two trees only connect at the point you decided to merge them.
If you want all of the history of each sub-project to merge in...
This is quite a bit more difficult. The basic idea is that you'd choose the latest commit from the master project and rebase the entire sub-project onto that point, so the whole sub-project - i.e. all of its commits - grow out from that point, and then you'd merge the head of the sub-project back into the master project, maybe with --no-ff (no fast-forward) so you could see the whole sub-project in a commit bubble. This requires that all of the history of the sub-project be in the project-name subfolder (i.e. 'foo' from the first section).
This would require a ton of manual work, or something with git filter-branch
that I'd have to work on for awhile - I can't come up with it off the top of my head. I'm guessing it would be a --tree-filter
, and you'd have to move everything that wasn't in the 'foo' folder into it per commit. I don't know how this handles branches and merges in the project, but I suspect it works. I'll refrain from trying to figure this out in case you're fine with the first suggestion with multiple roots (I think it's the better option of the two).
If you don't mind multiple roots, but want to be able to send work back upstream...
If this is it for the sub-projects - they're going into this repo forever, and will never see the light of day again, either of the first two variations would be fine. If you occasionally want to push things back upstream, you should look into git submodules and subtrees.
Submodules essentially let you clone a repo into a particular folder in your project. Your project only tracks which commit it should be on. When you clone your main repo, the submodule folder won't exist. You can pull it in by doing git submodule init
to create the folder, and git submodule update
to pull in all the files.
Subtrees go a step further and read the entire sub-project directly into a folder of your choosing in the main repo. From that point on, that folder exists just like any other in your project. Most of the magic here comes from subtree merging, which allows you to pull in changes from the sub-project without all the history, and push changes back out the other way.
Given the option of all 3, I'd prefer to use submodules or subtrees. They're the clean way to handle merging repos together.