Migrating code from one Git repository to another while keeping the history

Published on - Updated on

Within the software development community, there is often a debate about keeping your code in a single monorepo or splitting it into multiple smaller repositories. This article will not discuss the advantages and disadvantages of one approach over the other. It will show you how to migrate code between Git repositories safely when you need to do so.

Step 1: Install git-filter-repo

While Git has the filter-branch command, its authors no longer recommend its usage due to its many limitations and risks. Instead, the Git documentation of the filter-branch command redirects you to an open-source tool called git-filter-repo. Install this tool using the command below.

curl https://raw.githubusercontent.com/newren/git-filter-repo/main/git-filter-repo > git-filter-repo
chmod +x git-filter-repo

Step 2: Make a fresh clone of the source repository

Use git clone to make a fresh copy of the repository from which you want to migrate files. We will use this repository to extract the necessary parts of the Git history without damaging or changing your development version.

Step 3: Extract relevant history

Run git-filter-repo from the source repository's root directory to remove everything unrelated to the files you want to migrate to another repository.

git filter-repo --subdirectory-filter <name of the directory you want to migrate>

The above command removes all files not in the given directory from the repository and their associated Git history. It also removes the directory and moves all its child files and directories to the repository's root. Often, this is not what you want, so you can run another git filter-repo command to move the files to the proper subdirectory.

git filter-repo --to-subdirectory-filter <new subdirectory>

Now, the files in the source repository are ready to be migrated to the target repository.

Step 4: Pull in the source files in the target repository

As with the source repository, create a fresh clone of the target repository, using git clone, before you run any commands.

Next, we'll add a remote to our target repository and point it to the modified source repository we created in the previous step.

git remote add source-repository <path to source repository on your local machine>

Fetch the history from the source repository using a git pull command. (below, we assume that you were on the main branch in the source repository)

git pull --allow-unrelated-histories --no-rebase source-repository main

That's it. The files from the source repository have been added to the target repository while keeping the Git history intact.

Step 5: Push your changes to the remote

As a final step, once you've double-checked everything, use git push to push the changes you made to the remote repository.