I'm trying to combine two branches each with different root commit into a new, empty branch. This is not the usual merge thing as i don't want to have the branches combined only in the last commit (in that case, the new branch would have a merge commit and 'below' still two seperate histories. The new branch would still have two root commits.).
One important fact in my scenario is that both branches are completely unrelated. None commit of either branch affects pathes of the other branches' commits => There will be no conflicts.
Let's assume the following branches:
A---B-----C-D
X---Y-Z
This is what i am looking for:
A-X-B-Y-Z-C-D
The main point is that i want to have the commits in chronological order. How to achieve?
Quick simple solution to merge is,
suppose A---B-----C-D (is branch 1) and X---Y-Z (is branch 2). Take all the patches from branch-2 (git format-patch -n) then apply all the patches on top of branch 1 (git am *.patch), and then shuffle where ever you want the sequence to be using git rebase -i HEAD~n
Hope that helps!
You write:
Of course, the "splicing" operation you suggest is probably a bad idea if you anticipate that many conflicts will arise. Let's assume that, indeed, nothing bad will happen.
If, at the beginning, your repo looks like this
you can follow the procedure outlined below to automatically "splice" commits from both branches into a single branch, while maintaining chronological order.
"Splicing" two unrelated branches
Make sure you're in a clean working state; then check out
branch1
and mergebranch2
into it:That will yield
Now, I know that's not what you want, but bear with me for a second. We will use merge commit
E
to have access to "the ancestry on both sides" at once.Check out
branch2
and reset it to commitA
.You'll be in the following situation:
Generate a list (in chronological order) of all the non-merge commits reachable from
branch1
but not frombranch2
:This should yield the following list of commits:
X
,B
,Y
,Z
,C
,D
; commitE
, which was created in Step 1 will not be in that list, because we used the--no-merges
flag.Cherry-pick those commits on top of
branch2
(A).Your repo will then look as follows:
Delete
branch1
:Edit: As you correctly remarked, because
branch1
is not fully merged into the current branch (branch2
), using just-d
won't do, here; you need to use the-D
flag instead.Your repo will then simply be
(Optionally) Rename
branch2
:Generalization to more than two branches
Let's assume you have n completely unrelated branches:
branch1
,branch2
, ...,branchn
, wherebranch1
corresponds to the branch whose root commit is the oldest commit in the entire repository; Let's call that commitA
.If you don't know which commit is
A
, you can identify it by runningThe commit ID of
A
will be the first listed in the output of that command. And you can identify which branch isbranch1
by running:Then the procedure outlines in the two-branch case becomes:
Create a commit that has access to the ancestry of all branches, by merging all branches other than
branch1
intobranch1
.(same as in two-branch case)
branch2
.