Splitting Your Git Repo While Maintaining Commit History
So you have multiple directories in your repo and you want to split that repo into multiple ones? In my case, I had a single repo that contained both my frontend JavaScript directory and my backend Ruby on Rails directory that I wanted to split into two so I could host them on Netlify and Heroku.
How to Split your Repo:
1. Check you are in the root directory of your repo.
Once you have cd’ed into the root directory, run a quick ls
terminal command to ensure all the sub-directories are listed.
While this isn’t necessary to split your repo, a fun way to check your repo’s git history is to run git log
or git log --onelist |wc
if you want to see how many commits that branch of the repo has (it’s the first number listed).
2. Check you are in the master branch
This is assuming you want to split the master branch. If not, make sure you are in the right branch.
Write git branch
in your terminal to ensure you’re in the master branch.
3. Exit the Root directory
From the root directory, cd ..
back one level until you are one level above the root directory.
4. Move your Original Repo Clone to a New Directory
In your terminal type mv mv [your root directory]/ [your root directory].orig
. We do this because we are about to re-write the history of your repo.
Here’s what that previous two steps would look like for my repo where the original was called “bookclub-full-app”
If you check out your files on your computer, you’ll see that this repo has changed it’s name locally. On a mac this is in ‘Finder’
5. Create a New Clone of your Repo
Ensure you are on level above your newly renamed directory (hint: if you haven’t cd’ed anywhere, you should already be there!).
Clone your repo again: using git clone [insert repo url here]
Double check you have both repos by doing a quick ls
check and ensuring both are listed. In my case I would have bookclub-full-app and bookclub-full-app.orig.
6. Decide Which Directory You Want to Split.
cd
into your newly cloned repo (not the .orig). You should be back to the root directory where you’ll see a list of all your files and directories within your repo. In my case I have the same three subdirectories listed:
Once you ensure you’re in the root directory, do the following command:
git filter-branch --prune-empty --subdirectory-filter [name of subdirectory you want to create a new repo for] -- master
In my case it looked like this to get just my backend:
filter-branch is the main git command to split your subdirectory from the root.
subdirectory-filter is what we use to say which subdirectory we want to split, so you write your subdirectory name directly after this.
— master at the end shows what commit we want to operate this on.
At the end, this will rewrite the history. You may get a notification about a gut of gotchas, just wait and it will complete after a few seconds.
7. Ensure you have Properly Re-written the Sub-directory and its History
If you type ls
now, instead of seeing the original subdirectories, you’ll have a list of the subdirectories of your filtered branch.
We went from this to this:
As you can see, your new root directory contains all the files you want in it’s own repo. You can test this out by typing git log
to ensure it has all the git history has been preserved.
8. Remove the Remote Reference to the Original Repository
Ensure you are in the new root directory type git remote remove origin
. If you get an warning about other branches, this can be ignored.
9. Add the New Repository Reference
You’ll need to create a new repo on GitHub and copy the url link for to do this. Once you have the url ready, do git remote add origin [new repo url]
.
10. Push All Your Files to the New Repository
git push --all
git push --tags
11. Clone your New Repo
cd ..
git clone [new repo url] [insert new repo name]
12. Celebrate!
You’ve officially split off a subdirectory and created its own separate repo while maintaining the git history. I had to repeat these steps again to separate my frontend from my original repo as well.
If you have any questions, comments, or thoughts on how to do this better, I always love learning how to do things better. Just let me know in the comments below.
If you want, feel free to check out my split frontend and backend repos for my bookclub project I’ve been working on called On the Same Page. You can see it live here, just be patient a moment while Heroku loads it!
Keep coding and carry on. Have a great day!
Sources:
- Dan Gitschooldude’s youtube video on splitting a repo into multiple repos
- Nassos Michas’ blog post on maintaining git history.