1

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.

Pedro
  • 81
  • 2
  • 7
  • Backup the files before trying this. Literally copy and paste the files into the structure you want. Making sure you copy the hidden .git and .gitignore folders. The cd into the parent `mainRepo` directory and init a git repo – S. Walker Nov 13 '17 at 00:26
  • @S.Walker, this will create submodules, wich wont work when my old repositories will be deleted, right? – Pedro Nov 13 '17 at 00:47
  • Git doesn't *have* file history. Git has commits, and commits *are* history. You either retain the old commits (and hence the old history), or form new commits (and hence new history). You must choose between these options, which then dictates what to do. – torek Nov 13 '17 at 01:41
  • Possible duplicate of [How to combine two separate unrelated Git repositories into one with single history timeline](https://stackoverflow.com/questions/9781729/how-to-combine-two-separate-unrelated-git-repositories-into-one-with-single-hist) – phd Nov 13 '17 at 13:38

1 Answers1

2

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')"
ephemient
  • 198,619
  • 38
  • 280
  • 391