git - How can I "splice" two (or more) completely unrelated linear branch ancestries into a new one? -


i'm trying combine 2 branches each different root commit new, empty branch. not usual merge thing don't want have branches combined in last commit (in case, new branch have merge commit , 'below' still 2 seperate histories. new branch still have 2 root commits.).

one important fact in scenario both branches unrelated. none commit of either branch affects pathes of other branches' commits => there no conflicts.

let's assume following branches:

a---b-----c-d   x---y-z 

this looking for:

a-x-b-y-z-c-d 

the main point want have commits in chronological order. how achieve?

you write:

one important fact in scenario both branches unrelated. no commit of either branch affects patches of other branches' commits => there no conflicts.

of course, "splicing" operation suggest bad idea if anticipate many conflicts arise. let's assume that, indeed, nothing bad happen.

if, @ beginning, repo looks this

a---b------c--d [branch1]    x---y--z [branch2] 

you can follow procedure outlined below automatically "splice" commits both branches single branch, while maintaining chronological order.

"splicing" 2 unrelated branches

  1. make sure you're in clean working state; check out branch1 , merge branch2 it:

    git checkout branch1 git merge branch2 

    that yield

    a---b------c--d---e [head=branch1]                  /   x---y--z------- [branch2] 

    now, know that's not want, bear me second. use merge commit e have access "the ancestry on both sides" @ once.

  2. check out branch2 , reset commit a.

    git checkout branch2 git reset --hard 

    you'll in following situation:

    a [head=branch2]  \   ---b------c--d---e [branch1]                   /    x---y--z-------  
  3. generate list (in chronological order) of non-merge commits reachable branch1 not branch2:

    git rev-list --no-merges --reverse branch2..branch1 

    this should yield following list of commits: x, b, y, z, c, d; commit e, created in step 1 not in list, because used --no-merges flag.

  4. cherry-pick commits on top of branch2 (a).

    git cherry-pick `git rev-list --no-merges --reverse branch2..branch1` 

    your repo follows:

    a--x'--b'--y'--z'--c'--d' [head=branch2]  \   ---b-----c-d---e [branch1]                 /    x---y-z------  
  5. delete branch1:

    git branch -d branch1 

    edit: correctly remarked, because branch1 not merged current branch (branch2), using -d won't do, here; need use -d flag instead.

    your repo be

    a--x'--b'--y'--z'--c'--d' [head=branch2] 
  6. (optionally) rename branch2:

    git branch -m branch2 <more_meaningful_name> 

generalization more 2 branches

let's assume have n unrelated branches: branch1, branch2, ..., branchn, branch1 corresponds branch root commit oldest commit in entire repository; let's call commit a.

a ----- o ---- o [branch1]     o ----- o ---- o -- o [branch2]  ...   o ----- o - o [branchn] 

if don't know commit a, can identify running

git rev-list --reverse --max-parents=0 --all 

the commit id of a first listed in output of command. , can identify branch branch1 running:

git branch -r --contains `git rev-list --reverse --max-parents=0 --all | head -1` 

then procedure outlines in two-branch case becomes:

  1. create commit has access ancestry of branches, merging branches other branch1 branch1.

  2. (same in two-branch case)

  3. (same in two-branch case)
  4. (same in two-branch case)
  5. delete branches other branch2.
  6. (same in two-branch case)

Comments

Popular posts from this blog

php - Submit Form Data without Reloading page -

linux - Rails running on virtual machine in Windows -

php - $params->set Array between square bracket -