Search code examples
gitgithubmergegit-branchgit-subtree

Merge multiple git repositories into one, keeping branches history


I have four separate projects. They have their own git repository. and the same name of branches for all projects.

 /project/
 /project/projA/
 /project/projA/.git/
 /project/projB/
 /project/projB/.git/
 /project/projC/
 /project/projC/.git/
 /project/projD/
 /project/projD/.git/

All git repositories have the same name of branches, and of course their own master branch.

Question

I would like to merge all projects into one like so:

  /Project/.git/
  /project/projA/
  /project/projB/
  /project/projC/
  /project/projD/

But

i want to keep the history of all branches.

ps -> i have the same name of branches for all repo. for exemple: a branche name used for all four project: V6-004

Details

I tried submodule and subtree but the both doesn't solve the issue.

I tried also this.

  $ mkdir new_parent_project
  $ cd new_parent_project
  $ git init
  # Now we need to create the initial commit. This is essential.
  $ touch README.md
  $ git add README.md
  $ git commit -am "initial commit"

after

  # merge project ProjA into subdirectory ProjA
  $ git remote add -f ProjA http://GitUrl
  $ git merge -s ours --no-commit ProjA/V6-006
  $ git read-tree --prefix=ProjA/ -u ProjA/V6-006
  $ git commit -m "merging ProjA into subdir: ProjA"

after

  # merge project ProjB into subdirectory ProjB 
  $ git remote add -f ProjB http://GitUrl
  $ git merge -s ours --no-commit ProjB/V6-006
  $ git read-tree --prefix=ProjB/ -u ProjB/V6-006
  $ git commit -m "merging ProjB into subdir: ProjB"

but

the projects are merged but i have only the history of V6-006. but i don't have history for the others branches.


Solution

  • That solution is not so far from what you tried. This works only if your different projects have no common files (otherwise it can be difficult to solve conflicts)

    # create a new repo:
    git init all_projects
    cd all_project
    # to make it more easy to understand, let's create a new branch
    git checkout -b main
    
    # import 1st project
    git remote add projectA http://projectA
    git fetch --all --tags
    git checkout masterA projectA/master
    git rebase masterA main
    # move the main branch to the current state
    git branch main -f
    # Now your branch main is at the same state as your A project
    
    # import 2st project
    git remote add projectB http://projectB
    git fetch --all --tags
    git checkout masterB projectB/master
    git rebase masterB main
    # move the main branch to the current state
    git branch main -f
    # Now your branch main contains all commits from projectA and projectB
    
    # etc..
    

    The result will be a repository with 1st all commits from project A, then all commits from project B, even if the project B has some commits dated before the last commit of project A, but this should not be a problem (and the history tree will be easier to read)

    EDIT : Sorry I just notice this not solve your problem to get all remote branches. Maybe you can find a solution based on that question, with something like this:

    for i in $(git branch -r |grep projectA|awk -F'/' '{print $2}'); do
      git checkout $i projectA/$i
      git rebase $i main
    done
    

    but this would make your tree more complex because all branches will starts from the main commit ..