Skip to content

Instantly share code, notes, and snippets.

@acg
Created July 10, 2023 17:31
Show Gist options
  • Save acg/a4cfd3cc139704a8801827c60b8fecee to your computer and use it in GitHub Desktop.
Save acg/a4cfd3cc139704a8801827c60b8fecee 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