Combining git repositories

Prior to this semester, I had been keeping my code for every class in a separate repository. This semester, I realized that adding another 4-5 repos to my GitHub every term was probably a bad idea. I wanted to consolidate them all into a single git repo.

The only issue?

I didn’t know how to combine the repos and keep the commit history for all of them separate repos. Since my GitHub activity consists almost entirely of commits on schoolwork, I didn’t want that to disappear when I deleted the old individual repos.

I did a bit of research, but most of the instructions I read suggested squashing the commit histories of old repos when merging into new. The process below is the one I came up with, and my activity timeline on GitHub shows the exact same statistics that it did before combining the repos. It may go against git/GitHub best practices, but for personal work and my purposes, it worked well enough.

Prepare each repo that you wish to merge into the new repo

Make a subdirectory at the top level of the repo to hold all the repo’s contents, and move all the files from the top level of the repo into the new subdirectory. Maybe your shell-fu is stronger than mine, but I found this easiest to do graphically. Just make sure you don’t move .git/!

Commit and push the moves:

git add .
git commit -m "Prepare for merge to <username>/<new_repo_name>"
git push origin master

Repeat for all of the repositiories that will be merged.

Consolidate the repositories

Create an empty repo on GitHub.

Clone the empty repo && cd into it:

git clone <url_to_new_repo>/<new_repo_name>
cd <new_repo_name>

Create an empty commit:

git commit --allow-empty -m "Initial commit"

Create a remote for each of the old repos:

git remote add <old_repo_name> <url_to_old_repo>
# repeat for each old repository

Fetch them all:

git fetch --all

Create a branch from the remotes for each of the old repos:

git branch <old_repo_name> <old_repo_name>/master
# repeat for each old repository

Checkout the branch of each of the old repositories and make sure the files are there:

git checkout <old_repo_name> && ls
# repeat for each old repository's branch

Go back to the master branch:

git checkout master

Merge and commit each of the branches from the old repositories:

git merge --allow-unrelated-histories <old_repo_name> master -m "Merge <old_repo_name> branch"
# repeat for each old repository's branch

Remove the remotes for the old repositories:

git remote remove <old_repo_name>
# repeat for each old repository's remote

Remove the old branches:

git branch -D <old_repo_name> # ... <old_repo_name_2> ... etc.

Push the new repo:

git push