I apologize if my notation or terminology is wrong. I have been using git
for a while on my personal projects and haven't had to deal with complicated merging scenarios. We started using it at work and are running into more complex scenarios. I am still a git
newbie so I'd like to figure out the best practices for cherry picking.
Scenario One
Here, we have a master
, fix
, and develop
branch. After we branched fix
, we updated the version number to 1.0.1
. We did the same for develop
, and changed the version number to 1.1.0
.
Let's say that fixes F1
, F2
, and F3
were committed to fix
. Out of these, we care about fixes F2
and F3
, but not about F1
because it is a change to a deprecated feature. We also don't care about the change in version number to 1.0.1
.
Now we can merge these changes back into master
from fix
without a problem. But what if I want to merge those changes into develop
? Right now I am using git cherry-pick
to pick out F1
and F2
. Also, for a large number of commits, I am using a range of commits to cherry-pick and that seems to work fine. Is this the best way of doing things?
That brings me to the next scenario regarding git cherry-pick
:
Scenario 2
Again, I apologize if the terminology is incorrect, or if my graph does not make sense. This is as best as I could describe it.
So in this scenario, we have a hotfix
branch in addition to the ones above. Let's say that someone committed hotfixes H1
and H2
into hotfix
, and then merged those changes into master
, fix
, and develop
.
At around the same time, someone else committed fixes F1
, F2
, and F3
into the fix
branch, but in a staggered manner (so F1
was committed before H1
, and H2
was committed before F3
. Now the person working on fix
wants to sync up, so he runs a git pull
, which brings those changes in order. Let us also assume that there were no conflicts.
Now, let's say this person wants to merge all his fixes into develop
. In this scenario, what will happen if he used git cherry-pick
with a range of commits starting at the commit for F1
, and ending at the commit for F3
? Would those merges be ignored? As far as I know, you are unable to cherry-pick merges (because you need to specify the main line). So in this case, will git cherry-pick
simply ignore those merges?
Also, to not have to deal with this scenario, is it better to always rebase
instead of doing a git pull
, so that your changes are applied after? That way you could specify the range of commits and it wouldn't include the merges.
Thank you, and I apologize if my question is stupid or if it does not make any sense.
Scenario One
Right now I am using git cherry-pick to pick out F1 and F2.
You mean F2 and F3, right? Essentially this:
git cherry-pick F1..F3
If so, that's fine. Alternatively you can create a temporary branch and rebase that:
git checkout -b for-develop F3
git rebase --onto develop F1
git checkout develop
git merge for-develop
You don't actually need to create the branch, as you can use SHA-1's directly, or reflogs, however, I used a branch for simplification purposes.
Note that git rebase
is basically a glorified cherry-pick, so at the end of the day it will do the same thing.
Scenario Two
What will happen if he used git cherry-pick with a range of commits starting at the commit for F1, and ending at the commit for F3? Would those merges be ignored?
You can tell cherry-pick to ignore the merges with --no-merges, so the merge commits themselves will be ignored (M1, M2), but not the commits themselves (H1, H2). Since you already have those in 'develop' that might create some issues. That wouldn't be a problem if git cherry-pick --skip
was implemented (I sent patches for that but were never applied).
But you can tell cherry-pick to ignore the commits that are already there as well:
git cherry-pick --no-merges --right-only --cherry-pick develop...F3
You can try git log
with the same arguments to see which commits would be cherry-picked. Or you can just specify them yourself:
git cherry-pick F2 F3
Finally, you can use git rebase
just the same:
git checkout -b for-develop F3
git rebase --onto develop F1
git checkout develop
git merge for-develop
Notice that git rebase
will do the same as the cherry-pick command I put above, and you can use the same git rebase
commands in both scenarios. You can also use the same git cherry-pick
command in both scenarios (with --no-merges --right-only --cherry-pick). You might run into some trouble if there are conflicts, and specifically if the commits turn empty (most likely already applied), since there's no git cherry-pick --skip
.
It's generally safer to use git rebase
, since that's what everybody uses, but if you feel adventurous, you can try git cherry-pick
for a while and see how that turns out.
Scenario 1 is fine as it is; indeed, cherry-pick seems like the best way to go there.
Scenario 2 is more problematic. I haven't tried it, but I suspect that git will have a hissy fit about trying to cherry-pick the merge commits. In this case, I think rebasing is your best bet. Merge commits are great things in some situations, but in this kind of interlaced scenario they get in the way and also tend to make your revision graph spectacularly complex. (Which it is, of course, but rebase lets you get away with that.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With