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.