Merging two unrelated git repositories into one might look like an ambitious task, but once you understand what’s happening, you will find out it’s pretty simple.
In this article, we will merge a git repository into monorepo. The example is demonstrated on a yarn workspace (which is a bunch of npm packages in one repository) and one npm package that should be merged into it. This is a common setup for a lot of front-end projects out there.
We start with two git repositories (monorepo and packageC) and end up with just monorepo, that will contain git history and all files from packageC.
Beware: This technique doesn’t allow you to merge tags from packageC.
TIP: If you don’t want to keep history, it’s way simpler to just copy files to the new repository and make a commit (KISS).
Even if you already have a copy of your source repository, I recommend making a new one. There will be changes and if something goes wrong, it’s easier to just delete and start over rather than trying to undo the changes (unless you know git very well).
## Replace packageC with your folder name
Moving all files in a source repository into
packages sub-directory will make your life easier. You will avoid conflicts when you later merge it into monorepo. Also, certain operations in your monorepo will become easier (e.g.: finding renames, making a diff based on a file path).
# The --prune-empty - removes commits which are empty due to the rewrite
Since now, the history will be rewritten as if all files were always located in
git filter-branch you can also extract package out of monorepo back into a single repository, but that’s a topic for another article.
Now everything is ready to be merged. But before we do so, I will shortly explain what is this
git merge --allow-unrelated-histories flag about.
By default, git won’t allow you to merge branch that doesn’t have a common ancestor. With this flag, we’re telling git that we know about it and that this merge is deliberate.
Git repository is always created with an initial commit, but in this case, we don’t have any. Our monorepo and packageC were created separately and thus have separate initial commits. To fix this, git will pretend that there was an empty initial commit that’s common for those unrelated histories. You can read more about it in the official documentation.
# Add remote in your monorepo to packageC
After a successful merge, it’s time for cleanup. Remove duplicate config files (
.eslint, …), delete old repository and fix your CI build.