Every time I want to combine two git repositories into a new high-level repository, I have to re-figure it out. I decided this time to write it down. Maybe someone else will find this useful too.
Here is my scenario: I have two repositories. I want to make a new empty repository and move the other two into it as subdirectories. I also want to preserve all the commit history of the original repositories.
Here are the steps involved for the first repository:
- Clone the first source repository
- Remove its origin ref so you dont’ accidentally push any screwups
- Make a subdir in that source repo named the same as the repo
- Move all the top-level files into that directory
- Commit that move.
- Create (or clone) your desination repository.
- Add a remote ref to it that points to the file location of your source repo clone.
- Pull from that ref
- Remove that remote ref.
You can now delete the clone of the source repository you, so you don’t really keep those file moves around in the original source if you don’t want to.
Here’s what those steps might look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Now you’re done and can delete the source repository clone, and push the destination repository clone upstream. Check the
git log to be sure.
A Concrete Example
Say I have two repositories on github named
bart and I want to combine them into a new repository called
simpsons. Here is how that looks:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
Bonus Points: Only Moving a Sub-Directory
What if you only want to move a subdirectory of the original source repository into the destination repository? All you need to do is filter out what you copy into that new sub-directory you create in step 4, and make sure everything else gets removed from that source repository. (Don’t worry - remember, you’re just working with a local working copy of that source repo, that you’re going top discard after this operation. You won’t harm anything irreversibly here.)
One way to peform that filtering is by using the
git filter-branch command. For example, to only copy the
pranks subdir from the
bart repo, just before step 4, you would do something like this:
That dumps all the contents of the
pranks dir into top-level dir where you can proceed to move them into your new subdir that you created in step 3.