Any suggestions for how to go from multiple Git repos to a monorepo? Preserving history would be really nice. I've looked at submodules and subtrees and both seem to have huge downsides and don't deliver the same benefits of a true monorepo.
Yes! I once had to merge a dozen or so repos into a mono repo. I don't have my script handy but git allows merging repos with unrelated histories into one repo while preserving the history.
If I remember correctly, this is how you do it:
1. Create a new empty repo for the monorepo
2. For each repo, 'git mv' all of the contents into a new directory with the repo's name
3. Add the repos to the mono repos as remotes
4. Run 'git merge --allow-unrelated-histories' for each repo
You will now have a monorepo with preserved history with each old repo existing inside of a sub-directory in the new monorepo
You just want to merge the repositories, there are plenty of guides online. You need to realize that git has pretty simple internals, so the procedure looks like this:
1. Inside one repository you add a reference to the other repository with `git remote add`.
2. When you do a fetch, git will just download all the objects from the other repository.
3. Then you check the files out and make commit.
You can do it in a few ways, for example, you might wish to preserve tags from all the repositories, but put them in their own namespaces, so you don't get conflicts. I wrote an answer on SO explaining exactly this: https://stackoverflow.com/questions/1425892/how-do-you-merge...
It's designed for making multiple Git repos from a monorepo, but I think you should be able to make a skeleton repo that represents your desired final monorepo layout and push your individual repos to the Josh subviews of that repo to combine them all.
(A big advantage of this approach over the multiple unrelated histories is that you don't have the mass move commits since Josh will rewrite all history as if the files were always in that folder, so you don't have to worry about history of individual files getting broken.)
You don't even need to make a skeleton repo first. By passing `-o merge` as extra option on the push to a non existing view, the merging of unrelated histories will be done by the server. See:
https://github.com/josh-project/josh/issues/596
Git as a system has no objection to having more than one 'initial commit'. It will happily take that branching history and merge it together. With a bit of branch renaming you can add extra remotes to your repo so both 'masters' are present. Commit to both to make the resulting directory structure not overlap, and then just merge. You'll end up with full history of both.
With Git I’m pretty sure you can literally just add a new remote to a completely unrelated repo, fetch it and then “merge” any branch from the other two into the new mono repo (ie. git checkout master; git merge other-remote/master). If all your projects are otherwise in a top level directory inside the monorepo this should merge cleanly and then can just live beside eachother in the checkout.