
Use Case: You have multiple related repositories that have existed for a long time that you would like to combine into a single monorepo, without losing the long informational git history of each one of those repositories.
Decide on the structure of your monorepoSection titled: Decide on the structure of your monorepo
You can of course organize your monorepo in any way you wish. The standard way is to have a packages
directory and sometimes an apps
directory (I think distinguishing those two different kinds of packages is nice).
However you decide, we need to initialize the monorepo with these directories. If you have an existing monorepo you’re adding to, you can skip this step.
cd ~/devmkdir monorepocd monorepo
git initgit commit --allow-empty -m "Initial empty commit" # Can't merge with an empty repo
# Define whatever structure you wantmkdir packagesmkdir apps
Then for each repo you want to move:Section titled: Then for each repo you want to move:
1. Move all files except for .git into a subdirectorySection titled: 1. Move all files except for .git into a subdirectory
The goal is to move each file into the same directory structure that you want it to live in inside the monorepo.
So if I have a my-app
repo, I’m going to move every file (except for the .git directory) into my-app/apps/my-app
because I want its final resting place to be monorepo/apps/my-app
.
There’s nothing wrong with just moving these fils with your OS file explorer; that is the simpler approach and works just as well. But here are commands to do it with the terminal:
cd ~/dev/my-app
# Create directory(s) to match the monorepo structure.# -p creates intermediate directories as required.mkdir -p apps/my-app
# Move all files, including dot files.# -k is used to ignore the error that apps/ can't be moved into itself.git mv -k * .* apps/my-app
Then you’ll need to commit that change:
git commit -m "chore: Move all files into apps/my-app"
2. Merge the existing repos history into the monorepoSection titled: 2. Merge the existing repos history into the monorepo
cd ~/dev/monorepo
# Add your other local repo as a remote inside of the monorepo.# -f fetches the repo state, needed to do the merge next,# You can also use a github/ButBucket remote instead of a local one.git remote add -f my-app ../my-app
# Merge the monorepo main branch into the my-app main branch.git merge my-app/main --allow-unrelated-histories
You’re totally done with this repo now, so you can remove the remote you added earlier:
git remote remove my-app
Now just repeat steps 1 and 2 for every repo you’d like to move over!
Acknowledgements
This post is largely a repackaging of a Medium article to add clarity and prevent it from being hidden behind a paywall. Big thank you to Chris Thompson for writing that.