Search code examples
gitgithubpull-requestcherry-pickgit-cherry-pick

How to open GitHub PR for a proposed cherry-pick


GitHub pull requests are all about merging two branches together:

  • The "remote" branch, containing new changes you want to merge.
  • The "local" branch you want to merge into, which GitHub calls the "base" branch.

Is there a way to create a branch that shows the same merge conflicts as a given cherry-pick, and that, when merged, is equivalent to performing that cherry-pick? In this instance we know the specific branch the cherry-pick will be applied to, if that makes any difference?

For example, is it sufficient to create a branch whose HEAD is the commit I want to cherry-pick, and open a PR for that branch?


Solution

  • A cherry-pick tries indeed to merge two patches together, but you will not be able to create a merge request on your work branch that does the same action as the cherry-pick.


    Detailed view of a cherry-pick :

    Here is my go at illustrating the merge operation performed by git cherry-pick :

    Suppose you run git cherry-pick eacf32 from branch my/work :

    # 'p' marks the parent commit of eacf32 :
    ---*-----*-----*------*-----* <- my/work
              \                   
               \               
                \-*---*----*----*-----*-----* <- some/other/branch
                           ^    ^
                           p   eacf32
    
    # 'git cherry-pick eacf32' will try to resolve this merge :
    
                             my/work
                              v
    ---*-----* . . * . .* . . *----* <- would-be-cherry-pick
              \              /    /
               \            /    /
                \-*---*----*----* . . * . . *
                           ^    ^
                           p   eacf32
    

    Turning it into an equivalent merge :

    Following this diagram :

    • you would want a branch cherrypick/target, with the actual content of my/work, grouped as one commit on top of p -- the parent commit of eacf32 :

      # start from your branch (you will have the expected content) :
      git checkout my/work
      # create a new branch and switch to it :
      git checkout -b cherrypick/target
      # use 'reset --soft' to move to the parent of eacf32
      # ('--soft' will keep all the differences as staged changes) :
      git reset --soft eacf32^
      # commit that :
      git commit
      
    • you would want a branch cherrypick/source at eacf32 :

      git branch cherrypick/source eacf32
      
    • you would merge cherrypick/source in cherrypick/target


    What to do with the result of this merge ?

    The possible merge conflicts and the content of the end result will be the same as the cherry-pick, you would obviously have to pick the content of that commit on top of your actual my/work branch.

    As you can see from the diagram : the merge base for the cherry-pick must be p, so you won't be able to create a PR against your initial my/work branch, which gives the same result as the cherry-pick.