How to cherry pick a range of commits and merge into another branch

I have the following repository layout:

  • master branch (production)
  • integration
  • working
  • What I want to achieve is to cherry pick a range of commits from the working branch and merge it into the integration branch. I pretty new to git and I can't figure out how to exactly do this (the cherry picking of commit ranges in one operation not the merging) without messing the repository up. Any pointers or thoughts on this? Thanks!


    When it comes to a range of commits, cherry-picking is was not practical.

    As mentioned below by Keith Kim, Git 1.7.2+ introduced the ability to cherry-pick a range of commits (but you still need to be aware of the consequence of cherry-picking for future merge)

    git cherry-pick" learned to pick a range of commits
    (eg " cherry-pick A..B " and " cherry-pick --stdin "), so did " git revert "; these do not support the nicer sequencing control " rebase [-i] " has, though.

    damian comments and warns us:

    In the " cherry-pick A..B " form, A should be older than B .
    If they're the wrong order the command will silently fail .

    If you want to pick the range B through D (inclusive) that would be B^..D .
    See "Git create branch from range of previous commits?" as an illustration.

    As Jubobs mentions in the comments:

    This assumes that B is not a root commit; you'll get an " unknown revision " error otherwise.

    Note: as of Git 2.9.x/2.10 (Q3 2016), you can cherry-pick a range of commit directly on an orphan branch (empty head): see "How to make existing branch an orphan in git".


    Original answer (January 2010)

    A rebase --onto would be better, where you replay the given range of commit on top of your integration branch, as Charles Bailey described here.
    (also, look for "Here is how you would transplant a topic branch based on one branch to another" in the git rebase man page, to see a practical example of git rebase --onto )

    If your current branch is integration:

    # Checkout a new temporary branch at the current location
    git checkout -b tmp
    
    # Move the integration branch to the head of the new patchset
    git branch -f integration last_SHA-1_of_working_branch_range
    
    # Rebase the patchset onto tmp, the old location of integration
    git rebase --onto tmp first_SHA-1_of_working_branch_range~1 integration
    

    That will replay everything between:

  • after the parent of first_SHA-1_of_working_branch_range (hence the ~1 ): the first commit you want to replay
  • up to " integration " (which points to the last commit you want to replay, from the working branch)
  • to " tmp " (which points to where integration was pointing before)

    If there is any conflict when one of those commits is replayed:

  • either solve it and run " git rebase --continue ".
  • or skip this patch, and instead run " git rebase --skip "
  • or cancel the all thing with a " git rebase --abort " (and put back the integration branch on the tmp branch)
  • After that rebase --onto , integration will be back at the last commit of the integration branch (that is " tmp " branch + all the replayed commits)

    With cherry-picking or rebase --onto , do not forget it has consequences on subsequent merges, as described here.


    A pure " cherry-pick " solution is discussed here, and would involve something like:

    If you want to use a patch approach then "git format-patch|git am" and "git cherry" are your options.
    Currently, git cherry-pick accepts only a single commit, but if you want to pick the range B through D that would be B^..D in git lingo, so

    git rev-list --reverse --topo-order B^..D | while read rev 
    do 
      git cherry-pick $rev || break 
    done 
    

    But anyway, when you need to "replay" a range of commits, the word "replay" should push you to use the " rebase " feature of Git.


    As of git v1.7.2 cherry pick can accept a range of commits:

    git cherry-pick learned to pick a range of commits (eg cherry-pick A..B and cherry-pick --stdin ), so did git revert ; these do not support the nicer sequencing control rebase [-i] has, though.


    Are you sure you don't want to actually merge the branches? If the working branch has some recent commits you don't want, you can just create a new branch with a HEAD at the point you want.

    Now, if you really do want to cherry-pick a range of commits, for whatever reason, an elegant way to do this is to just pull of a patchset and apply it to your new integration branch:

    git format-patch A..B
    git checkout integration
    git am *.patch
    

    This is essentially what git-rebase is doing anyway, but without the need to play games. You can add --3way to git-am if you need to merge. Make sure there are no other *.patch files already in the directory where you do this, if you follow the instructions verbatim...

    链接地址: http://www.djcxy.com/p/25258.html

    上一篇: 移动提交到一个新的分支(重命名分支,而不是强制推送?)

    下一篇: 如何樱桃选择一系列的提交并合并到另一个分支