27

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.

Anas ZAHOURI
  • 309
  • 1
  • 3
  • 11
  • 1
    "I tried submodule and subtree but the both doesn't solve the issue."... too bad: submodule is one easy solution in this instance. – VonC Oct 22 '14 at 08:30
  • 1
    yes but. This model works well when you want to include a third-party library in your project that only occasionally needs to be updated.On the other hand, if you use a submodule for a tightly-coupled library to which you will often be making changes, you will find that submodules are not the answer. – Anas ZAHOURI Oct 22 '14 at 08:32
  • Do you have only one branch (`master`) per subrepo to get into your repo? Or do those subrepos have multiple branches of their own? (in addition of their `master`) – VonC Oct 22 '14 at 08:34
  • yeah those subrepos have multiple branches of their own. – Anas ZAHOURI Oct 22 '14 at 08:36
  • You just want all the existing history on individual branches and in subdirs, and then a giant octopus merge at the end bringing everything together? – Andrew C Oct 22 '14 at 14:51
  • @AnasZAHOURI Hi, I'm going thought something similar. Did you manage to solve it in sane way? – Tomas Votruba Jan 22 '18 at 11:18

1 Answers1

14

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 ..

Martin Valgur
  • 5,793
  • 1
  • 33
  • 45
Asenar
  • 6,732
  • 3
  • 36
  • 49
  • 3
    I cannot get it to work, it gives an error on step `git checkout masterA projectA/master` saying that `error: pathspec "masterA" did not match any files known to git`. What should I put in "masterA"? – ESala Jun 08 '15 at 21:56
  • if git consider `masterA` as a file, that probably means that branch does not exists locally (neither remotely I suppose). Or maybe `git fetch` is missing – Asenar Jun 09 '15 at 11:50
  • @Asenar Do you have any idea what to do for two repositories that *do* share common files, namely one being a fork of the other without history? I'm [trying to figure this out here](http://stackoverflow.com/questions/38508600/how-do-i-combine-two-git-repositories-one-a-snapshot-of-the-other-with-current). – NobleUplift Aug 09 '16 at 19:57
  • Will this work when there are NO remote HTTP repos, but only local files? – przemo_li Oct 25 '16 at 09:21
  • 2
    @przemo_li remote repo can have url starting `http`, `user@server` or `/path/to/loca/dir`, so I don't see why this would not works. but you can check `git help clone` to see some interresting options (--no-hardlinks, --shared, …) – Asenar Nov 07 '16 at 15:27
  • 1
    I don't think this works, because masterA is required to end up in a subdirectory; now the merge and rebase only adds files to the main directory. – axd Oct 17 '17 at 14:38