I recently had to merge a number of independent projects into a larger project to enable a long-term project reorganization effort. Since we’re using Git for both projects, this was quite easy, but it required some investigating to figure out how to do it.

So you have two projects, old-project and new-project. You want to end up with a subdirectory inside of new-project called old-project with all of the code from old-project, and you want to preserve that project’s history.

For the purposes of this demonstration, old-project is cloned at /home/machete/old-project and new-project is cloned at /home/machete/new-project.

At the end of this, we want there to be a /home/machete/new-project/stuff/old-project with all of the commits from old-project intact.

The way we’re going to do this, it’s going to completely overlay old-project on top of new-project, so first we need to adjust the directories inside of old-project

cd /home/machete/old-project
mkdir -p ../stuff/old-project
mv * .gitignore ../stuff/old-project
mv ../stuff .
git commit -a -m "Preparing old project for move"

This just moves all of the files in old-project into a subdirectory structure matching what we want to have inside of new-project, then makes a commit.

Next we need to copy the history of this repository into new-project. So we don’t have to push our temporary move anywhere, we’re going to add our local directory as a remote git repository, then pull its changes in.

cd /home/machete/new-project
git remote add temp file:///home/machete/old-project
git pull temp master
git remote rm temp

This pulls the entirety of old-project’s history in. Since we did a pull (a fetch and then a merge), we will have a new commit at HEAD that has two parents, one for the regular old-project codeline, and one for the old new-project codeline.

That’s it, you can push new-project anywhere and the next fetch will pull down all of old-project‘s history.

UPDATE: it appears this no longer works as described, due to the error “Not a git repository”.

Basically what you’re trying to do is create a directory structure with a full git history for the old project, add that entire project as a remote, and pull down the changes with a merge.

So let’s say your old project is a github project. You could easily just move the directories around in that project, push up to the remote, then add the old Github project as a remote in the new project a pull down. The idea of the post is to let you do this locally without affecting the real repo, but unfortunately I seem unable to add local repos as remotes anymore. So instead, you can simply do all the file creation stuff with the ‘stuff’ directory above, but legitimately push to github. Then add github/old_project as a temp remote in new_project, pull it down, and you’re good. If you need to preserve the original, go back to github/oldproject and create a revert of the commit that does all the moving, then push that up.

Again, no idea why I can’t add repos on disk as remotes (even if cloned with –mirror), but it’s not an essential part of the steps.