30
  G---H             // Release Branch
 /
/
A---B---E---F---    // master
    \
     \
      C---D---     // bug fix branch

Based on our particular needs for our project, it is quite common for the above scenario to occur. We have our master/dev branch with some commits. Then we get a bug report and start fixing that on the bug branch (commits C and D above). More commits happen in the dev branch in the meantime. Next we are told we need to create a release for a customer which cannot include the changes introduced by commits B, E and F above, but it should include the bug fix.

So we branch off of dev before change B was ever applied, but what is the best way to get the bug fix into this release branch too? If I perform a merge of the branch it will include the change that was made in B which I don't want. I could perform a cherry-pick of commits C and D but I read that cherry picking is not always a good idea based on this answer basically because my repo would then look like:

  G---H---C'---D'--- // Release Branch
 /
/
A---B---E---F---     // master
    \
     \
      C---D---       // bug fix branch

So C' and D' appear as completely new commits with different sha-1 IDs as C and D. Is this really a bad thing? What problems can this lead to? Is there a better way of getting the changes from the bug fix branch into the release branch?

Community
  • 1
  • 1
DaveJohnston
  • 10,031
  • 10
  • 54
  • 83

4 Answers4

11

This article advises to instead of merging two branches, you would rebase them where git would only rebase non duplicate commits.

But instead of cherry-picking, you might consider just rebasing the branch:

rebase --onto release B bug

where release is the release branch and bug is the bug branch.

You then get something like

         C'---D' //Bug branch      
        /
       /
  G---H  // Release Branch
 /    
/ 
A---B---E---F---     // master

But this would mean that when you want the bug fixes to be applied to master that you would need to merge bug with master, which causes all the changes in release also to be added to master.

It's up to you to decide what works best for you.

Note that you should not rebase branches that have been pushed to other, because it will create a mess for them.

Dariusz
  • 15,573
  • 9
  • 52
  • 68
Ikke
  • 99,403
  • 23
  • 97
  • 120
5

There is no real danger in using cherry-pick, especially if you don't plan on ever merging the release branch into master.

In general, you can prevent problems like these by basing bug fixes on commits that are included in all branches you want to merge the fix into. In the development of git itself, that is achieved by merging all bug fixes into the maint branch (i.e. current stable series which only receives fixes) and then merging that into master periodically. That way, the fix is everywhere and the merges are sane.

Jan Krüger
  • 17,870
  • 3
  • 59
  • 51
  • And what is the danger if I do merge the release branch back to master? In the diagram I made, change H would eventually need to be applied back to the master branch. – DaveJohnston Jul 06 '11 at 12:37
  • Well, there is no problem if you don't also merge the bug fix branch into master. If you do that, it's possible that you get more conflicts than you would otherwise (if both branches modify those parts of the code in the same way and also add some different changes on top of that). "Dangerous" is an overstatement, really... all it means is that you'd have to manually fix a bunch of conflicts, and that the two commits will show up twice in your history (with different commit IDs). – Jan Krüger Jul 07 '11 at 12:24
3

Note: as explained above, cherry-picking is acceptable here.
Its main drawbacks are:

In your case:

  • no need to merge back.
  • if you are sure C and D aren't based on code introduced in B, ... cherry-pick them wherever you need them.
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
2

Create a patch file containing the unique content from the bugfix branch. Then apply that patch file to the release branch.

Example:

> git checkout bugfix_branch
> git diff B HEAD > unique_changes.patch /* where "B" is the point where bugfix_branch split from dev */
> git checkout release_branch
> git apply unique_changes.patch

Et voila! You now have only the unique changes from the bugfix branch in your release branch. Note that format-patch tends to more gracefully handle situations where files have been moved or deleted, so you may need to play around with the actual process by which the patch is generated, but this approach should get you close.

Eric Schnipke
  • 482
  • 1
  • 6
  • 22