Combining Two Repositories
Comment
The Problem
I was working for some time on two different repositories, one named
app-backend and one named app-frontend. After a few weeks of work,
I understood that this was a bad idea.
Instead of two separate repositories, I wanted a single repository
named app with two subdirectories frontend and backend.
The internet is full of articles that describe solutions of variants of this problem. The following solution is derived from these articles.
The Solution
The first step is to download the git-filter-repo script from
newren/git-filter-repo
and move it to some directoy where the shell can find
it. git-filter-repo is a standalone Python 3 script that does not
have any other dependency. (The installation of Python 3 is not
subject of the current little article.)
Now the content of the app-backend repository can be moved to the
backend subdirectory as follows.
cd app-backend
mkdir backend
git filter-repo --force --replace-refs delete-no-add --to-subdirectory-filter backend/
This moves every file under version control to the backend directory
while rewriting all the commits so that they look as if they had
happened in the backend directory right from the beginning.
Similarly, the content of the app-frontend directory can be moved to
the frontend directory as follows.
cd app-frontend
mkdir frontend
git filter-repo --force --replace-refs delete-no-add --to-subdirectory-filter frontend/
The reason for these two git-filter-repo operations is to create two
repositories that do not overlap when actually merging them as shown
below.
mkdir app
cd app
git init
git checkout -b main
git remote add backend ../app-backend
git remote add frontend ../app-frontend
git fetch --all
git merge backend/main --allow-unrelated-histories
git merge frontend/main --allow-unrelated-histories
Looking at the commits using something like git log -p shows that
the order of the commits is the expected one and that the commits look
as if they had been taken place in the respective subdirectory.
All that remains to do now is to care of the left-over files that were
not under version control. It may also be a good idea to merge
.gitignore files.
There are many recipes showing how to achieve similar results.
However, the ones that I looked at required to move files to backend
and frontend directories, respectively. And this would have introduced
large commits containing all of the code of the repositories. These
commits are avoided by using git-filter-repo as described above.