Dominik Honnef

Merging multiple git repositories

Last modified:

Today I had to merge a bunch of existing git repositories into a new monorepo. I had the following requirements:

The first two requirements meant that we could use neither subtree merges – as those break file history – nor ordinary merges – as those would put the contents of $repo in the root, not a subdirectory.

The solution is to use git filter-branch to rewrite the paths in the repositories, and only then merge the repositories into the monorepo. The final script looked like this:

projects=(proj1 proj1)

mkdir -p "$new_repo"
cd "$new_repo"
git init
git commit --allow-empty -m "Initial commit"
for prj in "${projects[@]}"; do
    git remote add "$prj" "$base/$prj"
    git fetch "$prj"
    git filter-branch -f --index-filter \
        'git ls-files -s | sed "s%\t\"*%&'"$prj"'/%" |
          GIT_INDEX_FILE=$ git update-index --index-info &&
          mv "$" "$GIT_INDEX_FILE"' "$prj/master"
    git merge -m "Merge $prj" "$prj/master"
    git remote rm "$prj"

Part of that script is based on an answer on Stackoverflow.

It should be easy enough to adapt this script for different needs (merging repositories from multiple sources, into different subdirectories and so on.)

Update: Beginning with Git 1.9, git merge refuses to merge unrelated histories unless the --allow-unrelated-histories flag is used.