This short post covers how to migrate an entire git repository inside another git repo while also preserving the commit history

Introduction

The Problem Statement

This might be a very niche use case but during my current workplace, I have felt twice the need to migrate the code in my local repository that I’ve been working on inside another upstream repo (that everyone uses) within a subfolder.
All while preserving the commit history.

I suppose you can guess now why copy and pasting all the code under the new folder won’t just cut it, which is why I thought of creating a post before I end up needing this for a third time while also helping other curious folks who find themselves on the same path.

Do note that this is different from adding the repository as a submodule in the target repo. As a submodule you still have 2 different repositories, but here we are unifying 2 different repos and merging it into the target repo.

The Idea

Git has this incredibly helpful feature of applying and creating patches and that is what we are going to utilise today.

This involves 2 steps:

  1. Converting the entire repo into a patch
  2. Applying that patch inside the target repository

Step 1: Converting Source Repo into a Patch

A “Patch” is basically a git commit but in a text file. It details the author of the commit, the message, the timestamp and the commit diff

We need to create a single file which contains all commits in the patch format


git format-patch --root --stdout > repo.patch

here,

  • --root sets the range from the beginning of the repository’s history
  • --stdout outputs the patch to the standard output instead of creating individual patch files and printing the filenames, which is the default behavior of format-patch

you should now have repo.patch file containing all the commits as a patch file


Step 2: Applying the Patch in the Target Repository

To preserve commit history and the commit date, we are going to use the git am command


Now inside the target repo run this command:

Warning: Make sure you apply the patch in a separate branch and not on main or master. This way you have a way to go back and redo everything if something fails

git am --directory=<the sub-directory you want to import to> --committer-date-is-author-date /path/to/repo.patch

here

  • --directory specifies the directory to import all the code to
  • --committer-date-is-author-date preserves the commit dates when the patches are applied (otherwise the current time is used for all the commits)

Summary

We’ve successfully converted an entire repository into a patch file and applied it to the target repository using the --directory and --committer-date-is-author-date flags.
Personally, I was surprised to discover the existence of the --directory fla. That made me wonder, did the authors anticipate this use case?

Anyways, that’s it! Check out git log --graph, and you’ll see all your commits present.

Updated: