Migrating a standalone GitHub repository into a larger monorepo while preserving the invaluable commit history is a common challenge for development teams. This process allows for better code sharing, simplified dependency management, and streamlined builds.
The most effective and recommended method involves using the powerful git filter-repo tool, followed by a strategic merge into the destination monorepo.
This guide will walk you through the process of moving an existing repository, which we'll call project-a, into a monorepo.
First, ensure you have git-filter-repo installed. It is a versatile tool for rewriting Git repository history.
You can install it using a package manager like Homebrew or pip:
brew install git-filter-repoor
pip3 install git-filter-repoNext, clone the repository that you intend to move into a new, temporary directory. This is a crucial safety measure to avoid altering your original repository.
git clone --bare https://github.com/your-username/project-a.git project-a-temp
cd project-a-tempThe --bare flag creates a minimal clone without a working directory, which is ideal for history manipulation.
Now, use git filter-repo to place the entire history of project-a into a subdirectory. This subdirectory will be its new home within the monorepo.
For this example, we'll use apps/project-a as the destination path:
git filter-repo --to-subdirectory-filter apps/project-aThis command will process every commit in project-a's history and rewrite it as if all the files originally existed within the apps/project-a folder.
Navigate to your existing monorepo's local directory. If you don't have one, you can create a new one.
cd /path/to/your/monorepoNow, add the modified project-a-temp repository as a remote to your monorepo. This will allow you to fetch its history:
git remote add project-a-temp /path/to/project-a-tempFetch the commit history from the temporary remote:
git fetch project-a-tempThe final and most critical step is to merge the history of project-a into your monorepo.
The --allow-unrelated-histories flag is essential here because the two repositories do not share a common ancestor commit:
git merge project-a-temp/main --allow-unrelated-histories -m "feat: Import project-a with full history"Replace
mainwith the name of your default branch if it's different. This command will create a new merge commit that integrates the entire history ofproject-ainto your monorepo.
Once you have verified that the merge was successful and all the files and commit history from project-a are present in the apps/project-a directory of your monorepo, you can remove the temporary remote:
git remote remove project-a-tempYou can also delete the project-a-temp directory:
rm -rf /path/to/project-a-tempFinally, push your changes to the remote monorepo repository:
git push origin mainBy following these steps, you will have successfully moved your GitHub repository into a monorepo while preserving its complete and valuable commit history. This process ensures a seamless transition and maintains the historical context of your project's development.