Git: split and merge repositories

2017-09-29

Our project is historically a combination of 2 projects, each of then had own repository. Let's call them P1 and P2. And we have a small team that works on a completely separate feature (Reports), they were previously not happy that they have to work in same repository (and have unnecessary dependency) but now their code is scattered in 2 repositories. So the task is, take subfolders from 2 repositories and merge them into one new repository.
  1. Create a new empty repository (let's call it P3)
  2. Clone locally: git clone [repositoryUrl]/P3
  3. make a first commit to create a master branch (I created .gitignore, anyway will be needed later): cd P3 bin > .gitignore git add . git commit -m "Initial commit with .gitignore" git push
  4. Clone the P1 with a proper branch (I actually did "cd .." first to get back to root folder) git clone -b [branch] [repositoryUrl]/P1 cd P1
  5. Filter the branches you need. Note that path should have slashes "/" (not backslashes), otherwise git says "Nothing to filter": git filter-branch --prune-empty --subdirectory-filter "[directory]" [branch]
  6. Add remote to the new repository (second command is just to check): git remote set-url origin [repositoryUrl]/P3 git remote -v
  7. Create a new branch: git checkout -b P1_migrated
  8. Create a new folder and move files there (otherwise you will have a mess when you merge from 2 repositories). Note to use "git mv" to keep history. I executed second command 3 times, you can use something more clever if you have many files. Also make sure to write folder names in proper casing - filesystem is not case sensitive but git repository is: mkdir P1 git mv [filename] P1 git add . git commit -m "Moved to P1"
  9. Push the changes in the new branch in new repository: git push -u origin P1_migrated
  10. Delete the folder: cd .. rmdir P1 /s /q
  11. Make steps 3-9 for the second project, you will get P2_migrated
  12. Go to the new repository and fetch the branches: cd P3 git checkout master git fetch
  13. Merge the migrated branches, with the switch to allow unrelated histories: git merge origin/P1_migrated --allow-unrelated-histories git merge origin/P2_migrated --allow-unrelated-histories
  14. And the final step: git push
I had to do steps 4-9 couple times to filter several directories, git cannot accept multiple directories in --subdirectory-filter. So instead of 7 I switched to the existing branch: git fetch git pull origin P1 --allow-unrelated-histories Git is powerful and can do cool things. Hope you will find this article helpful. At least I may use it later (and I did).
Sources used:

← Back to blog