So, I think a useful simple way to think of it is "git creates diffs when it needs to on demand."
When you're doing a cherry pick of say commit ce123, what you're asking git to do is:
1. Diff ce123 against its parent
2. Go apply that diff to some other branch
Likewise rebasing is the same, but with an extra step to apply the inverse of the diff to the original commit first, then rewrite the history.
One of the big advantages of this on demand diffing approach is it's much more robust vs conflicts. Back in the subversion days I wrote some shell scripts that did the equivalent of git cherry pick and rebase. I'd keep a couple extra copies of a checkout, would use the switch command to quickly put them into a specific state, then would just generate a diff manually to apply to my main working copy. It worked, and was often faster than manually copying text around between editor windows, but it was extremely conflict prone.
So this distinction, of whether you store snapshots and diff on demand, or store diffs and snapshot on demand, is somewhat subtle but has important consequences.