As I understand from http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html the rebased branch is ‘moved’ on to another one.
What I see during my tests, though, shows that the commits from the rebased branch remain in the history, so they are effectively duplicated.


Perhaps I’m missing something or don’t understand the purpose of rebase completely or both.
If what I see is the intended behavior, then why is it so?
There are two separate phenomena here.
The screenshot you posted, from gitk, shows the old commit still. That’s just the way gitk works; If you reload by hitting Ctrl+F5 rather than just F5 (That’s File > Reload rather than File > Update for you mouse users) you’ll see the old commit disappears because it’s no longer relevant.
There are lots of operations in Git that create commits. Even more that create file or tree objects in the file store. The fact that many of these objects are no longer used is irrelevant.
This has a whole bunch of advantages. In your example, it means that if you decided your rebase was a bad idea, your old commit still exists and can be recovered. There’s even a handy syntax for it:
topic@{1}refers to the commit thattopicpointed to before the last time it moved; here that would be immediately before the rebase.The Git object model is clever about this sort of thing. Having an extra commit like this lying around takes up very little extra space. For a rebase like the one you’re describing, I’d expect holding on to the old branch would cost at most a few hundred bytes.
Of course, that does add up over time. So
git gc(which is run automatically by certain commands every so often for you) runsgit prune. Andgit prunewill look for commits and objects that are old and no longer relevant and clear them out for you.None of this means your rebase hasn’t worked, just that the idea of rebase “moving” commits is a simplification. What rebase actually does is apply the differences between each commit and its parent to the new branch, and creates a new commit with those differences for each commit on the old branch. It then updates the branch such that, if you look at the branch history, it’s as if those commits were moved.