I've read @raymond-chen's Stop cherry-picking series but can't wrap my head around if the following problem can be solved without using cherry-pick:
The timeline is as follows:
v1.0.1
based off v1.0.0
. Feature F1 must not be included in that releaseHow can I acheive this without cherry-picking?
In retrospect feature F3 should have been branched from F2, but that's too late now. We don't want to rewrite git commit history on master branch.
I agree with the article's sentiment that you should generally try to avoid cherry-picking, when a better alternative exists. That being said, there's nothing inherently wrong with cherry-picking, but when you do it in long-lived shared branches, you create duplicate copies of the commits which can cause (a slight amount of) confusion when viewing the history, and sometimes lead to additional conflicts or even unintended side effects. At a minimum, if cherry-picking will result in duplicate commits in long-lived branches, I recommend using the -x option so that when viewing the history, one of the commits will show the trailer stating that the commit was cherry-picked. Note that when cherry-picking commits from unmerged feature branches this isn't necessary.
In your particular case, I can think of 3 options for achieving your goal:
F1
on master
. For some reason you don't want this feature included, so take it out. Whether you choose this option might depend on what your master
branch is supposed to represent. If it represents what you're releasing, then this is a good option. You can always add F1
back in later when it's ready to release. (Perhaps by reverting the revert.)F3
over to your new hotfix branch. Sometimes cherry-picking is the best choice, and that's OK. Note this is what Raymond Chen's article suggests doing in your scenario. (Here he suggests cherry-picking the right way to help you avoid cherry-picking the wrong way.)git switch -c hotfix F2
git merge -s ours M2 # this will bring in M2 without taking the changes
git merge M4
# now make your hotfix changes
That solves the immediate problem but creates a new one when you merge it into master
, since it effectively has the same result as reverting F1
(or M2
) but in a far more confusing way.
Side Note: you stated:
In retrospect feature F3 should have been branched from F2, but that's too late now.
That may be true, but if master
represents releasable code, then perhaps if you could do it over you would have held off on merging F1
into master
. If that's true, then option 1 of reverting F1
might be best, for now.
Tip: if you decide to revert F1
, and F1
was just an abbreviation for multiple commits on a feature branch, you can either revert each commit in the reverse order that they occurred, or you can revert the merge commit M2
. If there's more than 1 commit I almost always prefer to revert the merge commit.