2

I am trying to connect two independent commit trees into one repository.

Initially I have:

A--B--C--D (master1)

E--F--G--H (master2)
   \
    I--J (somebranch)

These tree have no common ancestor and are independent of each other (different files and directories). I want to rebase both master2 and somebranch (may be multiple branches in fact) onto master1.

It's easy to rebase just single branch with:

#simple reabse:
git checkout master2
git git rebase master1

which would give me:

A--B--C--D (master1)
          \
           E'--F'--G'--H' (master2)
E--F--G--H
   \
    I--J (somebranch)

Preferably I would like a single command to move both (or more) branches simultanously, to get result like this:

A--B--C--D (master1)
          \
           E'--F'--G'--H' (master2)
                \
                 I--J (somebranch)
pawrog
  • 108
  • 8

2 Answers2

2

You can use a lesser-known feature called grafts to splice the histories together.

$ echo `git rev-list [E] -1` `git rev-list master1 -1` > .git/info/grafts
$ git filter-branch --tag-name-filter cat master2 [other branches]

Or if there are multiple branches involved, and you don't want to have to list them all, you can do:

$ git filter-branch --tag-name-filter cat `git show-ref --heads | awk '{print $2}'`

(for more details, see answer 161928, or blog article or advanced instructions)

Community
  • 1
  • 1
jdsumsion
  • 14,473
  • 1
  • 15
  • 9
  • Thanks, I'm aware of the grafts feature, but I'm not aiming at connecting the trees, I need to rebase both master2 and somebranch onto master1. – pawrog Jun 14 '13 at 11:44
  • I don't know of a variant of the `rebase` command that does what you want. This accomplishes the same effect as using the `rebase` command (assuming they are truly independent files & directories) -- but it does it for all branches in a single command. – jdsumsion Jun 14 '13 at 11:50
  • Issue with graft here is that commit E` after filter-branch effectively removes all files from master1 :( – pawrog Jun 14 '13 at 12:16
0

I have answered this question here and here. The short answer, use rebase with the --preserve-merges option, but before join all branches into a common, artificial node with:

git checkout H
git merge -s recursive -Xours J # will generate a J2 node

The rebase:

git rebase --preserve-merges --onto D E^ J2

Where E^ is the parent of E and J2 the resulting node of the merge. If you use E instead of E^, node E won't be rebased.

See more detailed comments in the quoted posts.

carnicer
  • 494
  • 3
  • 9