Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it right to use git cherry-pick in these scenarios?

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

enter image description here

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

enter image description here

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.

like image 827
Vivin Paliath Avatar asked May 20 '14 00:05

Vivin Paliath


2 Answers

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.

like image 54
FelipeC Avatar answered Oct 17 '22 15:10

FelipeC


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.)

like image 1
ebneter Avatar answered Oct 17 '22 15:10

ebneter