This post shows how to use git subtree
commands to move git repositories around.
Perfect if you’re indecisive about monorepo vs multirepo.
Move a repo in a different repo as a subfolder
Use case: you want to move a library into a monorepo (because you read a post that says it’s cool).
Before:
Source repo Destination repo
| |
|-- src |-- packages
| \-- index.ts | \-- bar
|-- package.json \-- README.md
|-- package-lock.json
\-- README.md
After:
Destination repo
|
|-- packages
| |-- bar
| \-- foo (**moved here from source repo**)
| |-- src
| | \-- index.ts
| |-- package.json
| |-- package-lock.json
| \-- README.md
\-- README.md
Steps:
- Clone the source repo in a folder named
source
- Clone the destination repo in a sibling folder named
destination
- In the destination repo, run:
git subtree add -P packages/foo ../source master
(assuming the main branch is calledmaster
) - Delete the source repo (I’m sure you won’t regret it)
Move a subfolder to a new repo
Use case: you want to move a library out of a monorepo into its own dedicated repo (because you read a different post that says monorepos are actually not cool).
Before:
Source repo
|
|-- packages
| |-- bar
| \-- foo
| |-- package.json
| \-- README.md
\-- README.md
After:
Destination repo (**keeping only the contents of foo**)
|-- package.json
\-- README.md
Steps:
- Clone the source repo in a folder named
source
- Prepare a new empty bare repo in a folder named
destination
(withgit init --bare
) - In the source folder, run
git subtree push -P packages/foo ../destination master
- To double check everything went fine, you can clone the bare repo into a regular repo and inspect its contents.
- Delete the library from the source repo
Move a subfolder to an existing repo
Use case: you have two monorepos and you want to move one library from one to the other (because the oxymoron of having multiple monorepos escapes you).
Before:
Source repo Destination repo
| |
|-- packages |-- libs
|-- bar \-- bar
\-- foo
After:
Source repo Destination repo
| |
|-- packages |-- libs
\-- foo |-- bar
\-- bar_v2 (** moved here from source repo where it was called bar **)
- Clone the source repository into a folder named
source
- Clone the destination repository into a sibling folder named
destination
- In the source repo, keep only the desired library with
git subtree split -P packages/bar -b temp
(temp is the name of a branch we’ll use next) - Checkout the
temp
branch and double check the source repo folder only has the desired library - In the destination repo, add the library with
git subtree add -P libs/bar_v2 ../source temp
- Delete the library from the source repo
Update: 2021-10-03
I have a put together a script that handles some of these cases (especially the moving back to multirepo part).