Reputation: 333
Another git question... I am in the following situation:
A1 ---- B1 ---- C1
\
> D ---- E ---- F
/
A2 ---- B2 ---- C2
Where {A1,B1,C1} and {A2,B2,C2} have no files in common (it's the consequence of merging two different repositories, so I have currently two roots)
I would like the history to look like this
A1 ---- B1 ---- C1 ---- A2 ---- B2 ---- C2 ---- D ---- E --- F
But I cannot figure out how to do that with git-rebase, any idea?
Bonus: If I can keep the tags (which I have on all three branches) without having to do it manually...
Upvotes: 3
Views: 111
Reputation: 2322
I managed to do it with the following two commands, in sequence:
git filter-branch -f --parent-filter 'test $GIT_COMMIT = <a2> && echo "-p <c1>" || cat'
git filter-branch -f --parent-filter 'test $GIT_COMMIT = <new head> && echo "-p <c2>" || cat'
Of course, you have to replace <a2>
, <c1>
, <new head>
etc. by the corresponding commit hashes. Note that the head's hash changes after the first command, which is why I called it <new head>
instead of just <d>
.
It's actually pretty straightforward: the first command sets C1 as A2's parent. The second command fixes the graph by setting C2 as D's only parent.
Upvotes: 3
Reputation: 333
Ok I figured out a way to do that. Since it gives a big up in the understanding of the internals of git, I give a detailed answer here:
First, you have to give to A2 a new parent, since it didn't have before:
git cat-file commit A2
produces a summary where no "parent appear". So create the line, and create a new hash:
git cat-file commit A2 | sed -e '2aparent C1' | git hash-object -t commit -w --stdin
This will give a hash {H1} as an output, that we use to replace A2 by this new hash:
git replace A2 H1
And voila, the A2 has now C1 as parent. But now the history looks like that:
A1 ---- B1 ---- C1 --------------------- D ----- E ----- F
\ /
A2 ---- B2 ---- C2
So do the same to D, which has two parents (C1 and C2):
git cat-file commit D
Remove the "parent" line corresponding to C1, and hash, and replace:
H2=`git cat-file commit D | sed -e '/parent C1/d' | git hash-object -t commit -w --stdin`
git replace D H2
It looks like it worked for me. If I understand well what I did, this worked well because I had different files on both repositories. I think things could get wrong if I had files common in both repositories that were merged in a way in D.
Upvotes: 1