Search code examples
gitgit-mergegit-subtree

Merge git repositores


I have three GIT repositories:

  • Repo1
  • Repo2
  • Repo3

and i want to unify them into a single repo, like so:

mainRepo/Repo1

mainRepo/Repo2

mainRepo/Repo3

where every old repository is a subfolder of the new one. The mainRepo is a new repository, without anything inside.

The old repositories will be deleted, so there is no need to keep the remote, and i need to keep file history. I have tried to do it with subtree and manually merging, but didnt succeed.


Solution

  • This will preserve history (git log --follow).

    mkdir mainRepo
    cd mainRepo
    git init
    
    git remote add repo1 (path to repo1.git)
    git remote add repo2 (path to repo2.git)
    git remote add repo3 (path to repo3.git)
    git remote update
    
    repo1_commit=$(
        git commit-tree "$(
            printf '040000 tree %s\t%s\0' "$(git rev-parse repo1/master^{tree})" repo1 \
            | git mktree -z
        )" -p repo1/master -m 'Move repo1 to subdirectory')
    repo2_commit=$(
        git commit-tree "$(
            printf '040000 tree %s\t%s\0' "$(git rev-parse repo2/master^{tree})" repo2 \
            | git mktree -z
        )" -p repo2/master -m 'Move repo2 to subdirectory')
    repo3_commit=$(
        git commit-tree "$(
            printf '040000 tree %s\t%s\0' "$(git rev-parse repo3/master^{tree})" repo3 \
            | git mktree -z
        )" -p repo3/master -m 'Move repo3 to subdirectory')
    
    git reset --hard "$(
        git commit-tree "$(
            printf '040000 tree %s\t%s\0' \
                "$(git rev-parse repo1/master^{tree})" repo1 \
                "$(git rev-parse repo2/master^{tree})" repo2 \
                "$(git rev-parse repo3/master^{tree})" repo3 \
            | git mktree -z
        )" \
        -p "${repo1_commit}" -p "${repo2_commit}" -p "${repo3_commit}" \
        -m 'Merge repo1, repo2, and repo3')"