Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git octopus merge with unrelated repositories

Tags:

I have a bunch of git repositories, each containing one file. I'd like to merge them all together, preferably in one step. What I'm aiming for is this graph:

*----¬ mergedrepo/master | \ \ \ | | | * repoA/master | | * repoB/master | | | | | * repoB/... | * repoC/master * repoD/master | * repoD/... 

I tried a git merge, but it appears the octopus strategy doesn't work for disjoint trees

$ git merge a/master b/master c/master d/master Unable to find common commit with a/master Automatic merge failed; fix conflicts and then commit the result. 

I was also told that git merge --squash would help, but that gave the same error.

This generates the right graph, but loses all the files:

$ git merge -s ours a/master b/master c/master d/master 

How do I go about doing this?

like image 951
Eric Avatar asked Jun 03 '12 21:06

Eric


People also ask

Does merging affect both branches?

So merging one branch into another has a secondary effect: it moves the merge base of those two branches. In particular, the new merge base of the two branches is now the second parent of the merge commit.

What is git octopus merge?

Octopus Merge: Octopus Merge strategy resolves cases with more than two heads but refuses to do a complex merge that needs manual resolution. It is primarily meant to be used for bundling topic branch heads together. This is the default merge strategy when pulling or merging more than one branch.

Can I merge specific commit from another branch?

Go to either the git log or the GitHub UI and grab the unique commit hashes for each of the commits that you want. "Cherry pick" the commits you want into this branch. Run this command: git cherry-pick super-long-hash-here . That will pull just this commit into your current branch.


2 Answers

I've managed to resolve the problem with octopus merge of unrelated branches. Unfortunately the following applies only to rather simple cases where no real merge conflicts exist.

  1. Do a merge as described in the OP.

    git merge --allow-unrelated-histories a/master b/master c/master d/master

    It will "fail" claiming about conflicts. But the merge has been performed and that fact recorded although there are no changes in the index.

  2. Add contents of branches to the index with the read-tree command:

    git read-tree a/master b/master c/master d/master

    This will not affect working tree, only the index will be updated. (It is possible that you want to add your current branch to the end. You need to add all of them in one command.)

    If branches are not totally independent then adjust their order keeping in mind that the latter will overwrite contents of former branches.

  3. Commit normally. (git commit -m "octopus-merged remote 'a', 'b', 'c', 'd'")
  4. Perform a hard reset (git reset --hard) to get a consistent working tree.

I suppose one can later edit and amend this commit but I personally haven't tried this.

like image 60
Vertigo Avatar answered Sep 19 '22 02:09

Vertigo


Create an empty commit

git commit -m "Common commit" --allow-empty 

look at its hash with log -1 and add it to the grafts file without any parents

echo HASH_OF_COMMON_COMMIT >> .git/info/grafts 

then find all other roots with log --max-parents=0 and for each add their hash to the graft file with the above hash as parent

each HASH_OF_ROOT HASH_OF_COMMON_COMMIT >> .git/info/grafts 

and now, merge!

The grafts file is a way to change the parents of a commit and once all your repos have a common commit your repo should accept the merge.

like image 43
akuhn Avatar answered Sep 20 '22 02:09

akuhn