My take on Git rebasing versus cherry-picking
As I've noticed recently, there's a
number of git problems that can be solved by either
git cherry-pick. Because I love
git rebase I started out
feeling that I should solve all of my problems with it (and resorting
git cherry-pick' was a weakness), but I've wound up convinced
that sometimes this is wrong. However, until very recently I didn't
feel that I understood when I wanted to use one or the other; instead
it felt like I was making it up as I was going along. In large part
due to learning from Aristotle Pagaltzis's
useful comments here, I've now wound
up with my take on when I want to try to use one versus the other.
Put simply, my take is that:
Git rebasing is for moving commits while cherry-picking is for copying them.
An obvious case of moving commits is '
git pull --rebase'; I'm
moving my commits from the old
origin/master to the new one.
Ultimately what makes something a move is that I don't really care
about the old versions of the commits I'm rebasing; I'll only go
back to them (via the reflog) if something goes badly wrong (for
example, perhaps the new upstream version I pulled is broken).
(If I look at rebasing as moving commits,
git rebase always
updating the current or target branch makes sense. The kind of
things where I'd want to leave the 'source' of the commits intact
is not a move.)
Generally if I want to leave the old version of my local commits
around as well as have a new version, that's a copy instead of a
move. At a mechanical level I may use '
git rebase' after the '
cherry-pick' to reorder commits and so on, but I'll start with a
cherry-pick. One case that I've come to see as a copy instead of a
move is transplanting my local changes on top of another branch in
order to use it for various reasons. This covers both the 'switch
from development to stable branch' and 'switch from mainline to
someone's experimental changes' cases in my collection of git
tree shuffles I was uncertain about.
I've also realized that this describes what I want to do when I'm
working with Github pull requests. My
old writeup used '
git rebase', but it was clearly awkward; any
time I'm making a branch and then later changing its upstream is a
warning sign. A much simpler approach is to pull down the PR(s),
check the appropriate one out as a new (local) branch, and then
simply cherry-pick my changes on to it with '
(This makes working with PRs the same as working with any other branch, which is really what I'd expect. If I want to cherry-pick when I'm moving from development to stable or stable to development, I want to cherry-pick for PRs too.)