问题
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?
回答1:
You write:
One important fact in my scenario is that both branches are completely unrelated. No commit of either branch affects patches of the other branches' commits => There will be no conflicts.
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
A---B------C--D [branch1]
X---Y--Z [branch2]
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
branch1and mergebranch2into it:git checkout branch1 git merge branch2That will yield
A---B------C--D---E [HEAD=branch1] / X---Y--Z------- [branch2]Now, I know that's not what you want, but bear with me for a second. We will use merge commit
Eto have access to "the ancestry on both sides" at once.Check out
branch2and reset it to commitA.git checkout branch2 git reset --hard AYou'll be in the following situation:
A [HEAD=branch2] \ ---B------C--D---E [branch1] / X---Y--Z-------Generate a list (in chronological order) of all the non-merge commits reachable from
branch1but not frombranch2:git rev-list --no-merges --reverse branch2..branch1This 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-mergesflag.Cherry-pick those commits on top of
branch2(A).git cherry-pick `git rev-list --no-merges --reverse branch2..branch1`Your repo will then look as follows:
A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2] \ ---B-----C-D---E [branch1] / X---Y-Z------Delete
branch1:git branch -D branch1Edit: As you correctly remarked, because
branch1is not fully merged into the current branch (branch2), using just-dwon't do, here; you need to use the-Dflag instead.Your repo will then simply be
A--X'--B'--Y'--Z'--C'--D' [HEAD=branch2](Optionally) Rename
branch2:git branch -m branch2 <more_meaningful_name>
Generalization to more than two branches
Let's assume you have n completely unrelated branches: branch1, branch2, ..., branchn, where branch1 corresponds to the branch whose root commit is the oldest commit in the entire repository; Let's call that commit A.
A ----- o ---- o [branch1]
o ----- o ---- o -- o [branch2]
...
o ----- o - o [branchn]
If you don't know which commit is A, you can identify it by running
git rev-list --reverse --max-parents=0 --all
The commit ID of A will be the first listed in the output of that command. And you can identify which branch is branch1 by running:
git branch -r --contains `git rev-list --reverse --max-parents=0 --all | head -1`
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
branch1intobranch1.(same as in two-branch case)
- (same as in two-branch case)
- (same as in two-branch case)
- Delete all branches other than
branch2. - (same as in two-branch case)
回答2:
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!
来源:https://stackoverflow.com/questions/25928921/how-can-i-splice-two-or-more-completely-unrelated-linear-branch-ancestries-i