gitbranching-and-mergingfeature-branch

How can I move old commits in a branch to a new branches?


I have a branch called staging that contains old commits that I would like to move to two separate branches.

A - B - C - D - E - F - G - H - I   staging

I would like to move commits B and C to a new branch: feature-a. Then move commits D, E, and F to a new branch: feature-b.

In the end my branches would look like this:

A - G - H - I   staging
A - B - C       feature-a
A - D - E - F   feature-b

The staging branch is public and other developers may have local versions of it. How can I accomplish this?


Solution

  • NB: There is probably a better way, but here's one way to do it.

    Creating feature-a is easy:

    git branch feature-a C
    

    We can create feature-b by creating a new branch based on A and then using cherry-pick:

    git checkout -b feature-b A
    git cherry-pick feature-a..F
    

    That r1..r2 expression is documented in the git-rev-parse man page:

    The .. (two-dot) Range Notation

    The ^r1 r2 set operation appears so often that there is a shorthand for it. When you have two commits r1 and r2 (named according to the syntax explained in SPECIFYING REVISIONS above), you can ask for commits that are reachable from r2 excluding those that are reachable from r1 by ^r1 r2 and it can be written as r1..r2.

    Lastly, we can use git rebase -i --root on the staging branch to remove commits B-F:

    git checkout staging
    git rebase -i --root
    

    In my test repository, this results in:

    $ git log --oneline staging
    15326ce (HEAD -> staging) This is commit I
    3862020 This is commit H
    a26f0bb This is commit G
    9bc662c This is commit A
    
    $ git log --oneline feature-a
    b390f07 (feature-a) This is commit C
    1489cd1 This is commit B
    9bc662c This is commit A
    
    $ git log --oneline feature-b
    f8f3c18 (feature-b) This is commit F
    0eb0b08 This is commit E
    4e2ed05 This is commit D
    9bc662c This is commit A