That is, in fact, a very good question, because commits are snapshots.
The reason rebase works is because rebase actually repeats git cherry-pick (with a bit of wrapping in the front to figure out what to choose, and more at the end to move the branch labels), and git cherry-pick works turning the commit into a set of changes.
Suppose, for example, that you have this sequence of commits:
A
To reorder the topic on mainline , we need (1) to find the commits that are on the topic , but not on the mainline (which are C , B and A along the top line, ending with the commit marked with * ), and then (2) copy them to the new ones the commits that we add below the tip of mainline .
At the beginning of the search, three post- * transactions complete and put them on the list (reverse ordered: A , B , C ) (it also omits the default commands, but there are no merges here). Then he picks a cherry for each fixation.
To make cherry pick A , Git differs A from * . This turns two snapshots into a set of changes. Git then applies the changes to the maximum declaration of mainline and commits a new commit, let it call A' , on an anonymous branch:
A
In cherry pick B , Git diffs B vs. A Applying these changes to A' , another commit B' occurs. Repeat for C to get C' :
A
Finally, Git unsticks the topic label from C and instead points to C' . The old chain is abandoned (although you can still find it via reflogs, and rebase copies the C identifier to the special name ORIG_HEAD ):
A
and now the overflow is complete.
Note that each copy is performed using Git merge mechanisms, if necessary (if the differences are not applied immediately). Each of these can lead to a merge conflict, requiring rebase to stop and get help from you. (Or, even worse, you may get the wrong merge, although this is rare in practice.)
And, of course, if you reorder the commits (by moving the pick lines in an interactive permutation), we simply change the order we select and apply each commit. Sweet cherry operations still work the same: compare the selected commit with its parent ( C vs B , A vs * , B vs A ).