April 8, 2020
Monorepos are all the rage. If you already have two git repositories but want to switch to a monorepo without losing history, look no further.
Monorepos let us version our back-end with our front-end, making compability easy with combined builds and deployments using a shared CI/CD pipeline. They also let us make assumptions about relative relationships between folders during development.
It is easier than you think to merge two separate repositories into one.
Say you have RepositoryA
and RepositoryB
, which you want to merge to create RepositoryC:
RepositoryA
:
\
\.gitignore
\webpack.config.js
\tslint.json
RepositoryB
:
\
\.gitignore
\Program.cs
New RepositoryC
:
\
\.gitignore
\RepositoryA
\webpack.config.js
\tslint.json
\RepositoryB
\Program.cs
You'll notice from the above differences that we have a few steps required:
In RepositoryA
,
RepositoryA
into a sub-directory RepositoryA
(except .gitignore
)
RepositoryA
RENAME
in git.git push -u origin HEAD
In RepositoryB
,
RepositoryB
into a sub-directory RepositoryB
(except .gitignore
)
RepositoryB
RENAME
in git.git push -u origin HEAD
In RepositoryC
,
Initialize your new repository (maybe clone an existing empty repository)
c:\RepositoryC> git remote -v
origin https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryC (fetch)
origin https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryC (push)
Create an initial commit (maybe add a README.md
file)
Add RepositoryA
and RepositoryB
as remotes
Run:
c:\RepositoryC> git remote add repository-a https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryA
c:\RepositoryC> git remote add repository-b https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryA
After:
c:\RepositoryC> git remote -v
repository-a https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryA (fetch)
repository-a https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryA (push)
repository-b https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryB (fetch)
repository-b https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryB (push)
origin https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryC (fetch)
origin https://some-example@dev.azure.com/some-example/some-example/_git/RepositoryC (push)
Fetch the latest from these newly references remotes
c:\RepositoryC> git fetch repository-a
* [new branch] master -> repository-a/master
c:\RepositoryC> git fetch repository-b
* [new branch] master -> repository-b/master
Merge each of these new branches into your repository
c:\RepositoryC> git merge repository-a/master --allow-unrelated-histories
RepositoryC
contained.c:\RepositoryC> git merge repository-b/master --allow-unrelated-histories
Note: You may need to manually merge and commit your merge at this point, depending on what you initial commit to RepositoryC
contained.
--allow-unrelated-histories
is the magic sauce. Read the docs
At this point, you should have your new file structure containing the full history of both repositories into one. 🎉
Push your new remote
c:\RepositoryC> git push -u origin HEAD
You did it!
Further reading...