Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save aod7br/9947d4e6b06db3dd56ca116cc28ad0ea to your computer and use it in GitHub Desktop.
Save aod7br/9947d4e6b06db3dd56ca116cc28ad0ea to your computer and use it in GitHub Desktop.
How to combine two git repos into a monorepo without `git merge`

Use Case

Suppose you have local checkouts of two git repositories, a and b. You'd like to combine them into a new git repo c ("the monorepo"). More specifically, you'd like to:

  1. Preserve the combined commit history.
  2. Keep the commits from a and b ordered chronologically in c, interleaving as necessary.
  3. Avoid new merge commits, because you're a rebase-only freak like me. Most answers on the internet use git merge.
  4. Ignore all branches of a and b other than master. It's possible to port them over, but would significantly complicate these instructions. So for now that's an exercise left for the reader.

Preliminaries

To sidestep merge conflicts completely, we'll be moving all files from repo a into a subdirectory a/ of the monorepo. Similarly, repo b will live under b/ in the resulting monorepo.

You'll need an external tool, git-filter-repo, for this part. Once you've installed it, it's simple to use:

cd a
git-filter-repo --force --to-subdirectory-filter a

Heads up: this will rewrite all history in your local checkout for a. If you'd like to preserve your checkout of a as it originally stood, you can create and use a temporary checkout with git clone ./a ./a.tmp.

Do the same for b.

Instructions

And here's how to create a new monorepo c, then combine the rewritten-to-subdirectories-history of a and b into it:

mkdir c
cd c
git init .
git remote add a ../a
git remote add b ../b
git fetch --multiple a b
git log --format="%ct %H" a/master b/master |
sort -k1n |
cut -f2 -d' ' |
xargs -n1 git cherry-pick
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment