Merging packages and their histories into a Lerna monorepo
Update: You probably just want to use lerna import. But if you'd like a manual technique, or aren't actually using Lerna, read on.
Let's say you have a Lerna monorepo called acme. You have a package called app, presently in its own repository, that you want to move into repo. And you want to preserve the whole git history of app in the merge, so it becomes part of the history of acme. The process is actually pretty simple.
acme looks like this:
acme
|-- package.json
\-- packages
|-- foo
\-- bar
So app is going to go join foo and bar in the pantheon of packages.
Plan ahead, because we are going to do a force-push over acme's master branch. Make sure your collaborators know what is about to happen.
The process
You'll need git-filter-repo. Go download that.
- Fork
app. We're going to push overmasterof this fork. - Clone your fork of
app. Thencd app. - Move the repo's contents into a subdirectory and update history accordingly using
git filter-repo --to-subdirectory-filter "packages/app"
The old contents of theapprepo should now all be contained inpackages/app. git push origin master --forceto push this crazy new history over your fork's history.cdover to theacmerepository- Add your fork of
appas a remote withgit remote add app git@github.com:you/app.git git merge app/master --allow-unrelated-histories- View the
git logand make sure it looks like you expect it to. - Sweet, forbidden fruit. Savor it:
git push origin master --force
Resolving works in progress
At this point you'll start getting messages from your colleagues asking what horrible thing you've done. You can help guide them a bit.
To update their master branch, they'll need to check out master, git fetch and then git reset --hard origin/master.
If they had a change in progress for app, they can usegit diff [some commit hash] > mychange.diff
to create a patch file that they can then apply to the acme repository using git apply mychange.diff.
If they had a feature branch on acme, they should be able to use git rebase origin/master -i to reconcile the histories.
If they just had some uncommitted work on acme, they should be able to do git stash, git reset --hard origin/master, then git stash pop.
Finishing up
You'll want to adapt app a little bit to its new home. You'll want to refactor these things (at least) out of app and into top-level files in acme:
- .gitignore
- ESLint config
- Prettier config/ignore
- Travis config
- Dev dependencies from
app/package.json