Fixing rebase rather than avoiding it

Michael Haggerty mhagger at alum.mit.edu
Wed Mar 10 12:32:38 GMT 2010


Stefan Monnier wrote:
> Hmm... maybe we don't talk about the same thing.  Here's the scneario
> I have in mind:
> 
> - input:    B1 <- B2 <- B3 <- B4 <- B5
>                   ^
>                   |
>                   C1 <- C2 <- C3
> 
> - normal rebase output:
> 
>             B1 <- B2 <- B3 <- B4 <- B5
>                                     ^
>                                     |
>                                     C1' <- C2' <- C3'
> 
> - new rebase output:
> 
>             B1 <- B2 <- B3 <- B4 <- B5
>                   ^                 ^
>                   |                 |
>                   |                 C1' <- C2' <- C3'
>                   |                              /
>                   C1 <- C2 <- C3 <--------------+

No, this isn't the correct representation of a rebase, because it
doesn't capture all of the ancestor information implicit in a rebase.

A crucial difference between a rebase and a merge is that changes are
rebased individually.  In other words, we don't just want the changes
introduced by C1'+C2'+C3' to be logically equivalent to those of
C1+C2+C3.  We want (individually!) C1' to be logically equivalent to C1,
C2' equivalent to C2, and C3' equivalent to C3.  This, for example,
makes it possible to review the rebased commits individually without
also having to take into account the changes from a merge commit later
in the series.  As was pointed out, this DAG also doesn't help if
somebody has branched from C1 or C2.

The correct DAG to represent this rebase is

            B1 <- B2 <- B3 <- B4 <- B5
                   ^                ^
                    \               |
                     \              C1' <- C2' <- C3'
                      \            /      /      /
                       \          v      v      v
                        ---------C1 <-- C2 <-- C3

This DAG can be published and will not cause problems even if somebody
else has branched from C1 or C2.

As has been suggested elsewhere in this thread, the parent links
C1<-C1', C2<-C2', and C3<-C3' should be treated specially--considered
when merging, but hidden (or hideable) from the user in most situations.

I wrote a few blog posts about "rebasing with history" that you might
find interesting [1].  They provide more examples and go into more
detail about this idea.

Michael

[1]
http://softwareswirl.blogspot.com/2009/04/truce-in-merge-vs-rebase-war.html
http://softwareswirl.blogspot.com/2009/08/upstream-rebase-just-works-if-history.html
http://softwareswirl.blogspot.com/2009/08/rebase-with-history-implementation.html



More information about the bazaar mailing list