Fixing rebase rather than avoiding it

Stephen J. Turnbull turnbull at sk.tsukuba.ac.jp
Sun Mar 7 06:37:41 GMT 2010


Stefan Monnier writes:

 > > The question is, *which* merge?  I think it's quite plausible that
 > > users would resolve conflicts differently if they occur in a grand
 > > merge of two branches vs. resolving them commit by commit in a
 > > rebasing process.
 > 
 > Doesn't matter.  Even if I do "bzr merge" twice in the same day, I may
 > not resolve the conflicts in the same way, and even less so if I pass
 > different --merge-type arguments.  So this "discrepancy" would not be
 > anything new.

The point is that it would become more frequent.

 > >> That's one of the cases of interest to me; and in that case adding
 > >> an arc is perfectly acceptable.

 > > Except to the person who's doing the rebase.
 > 
 > > I am quite sure that I would not use your rebase for the case it's
 > > designed for, though.  If I wanted the original base (or original
 > > commits) to show up as a parent(s) of the rebased branch, I'd use a
 > > proper merge.  The point of using rebase is to get rid of those arcs
 > > when there is no conceptual dependency (ie, conflict with the new
 > > base).  So those arcs need to be hidden, or at least hideable.
 > 
 > 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 <--------------+

This is what I have in mind when I say I would categorically refuse to
use it.  Either I really want to pretend that Ci' are "just patches"
that can be applied anywhere and don't depend on which reasonably
recent version is the base, and use a conventional rebase, or I want
to use a proper merge.

An extreme example of proper use of a rebase is a typo fix 'hte' -> 'the'
in a comment or string.  There is simply no good reason whatsoever for
trying to attach that to a particular point in the DAG, as long as it
is after the bug was introduced.  *This is by far my own most frequent
use of rebase.*

Note that this has the problem that branches sprouting from C1, C2, or
C3 are still screwed, even though strict mirrors of B2..C3 will be
handled correctly.

 > It's not the same as a "merge" because it generates more than
 > one commit.

OK.  We need new terminology for this, probably.

 > The more interesting things you'd like to do with history (that does
 > require modifying history) is when you want to take:
 > 
 >             B1 <- B2 <- B3 <- B4 <- B5
 >                                     ^
 >                                     |
 >                                     C1 <- C2 <- C3
 > 
 > and turn it into
 > 
 >             B1 <- B2 <- B3 <- B4 <- B5
 >                                    /^
 >                                  /  |
 >                                  |  C1 <- C2 <-------- C3
 >                                  |                    /
 >                                  C1' <- C2a <- C2b <-+

This cannot be done in current DVCSes, and I suspect I for one would
be willing to shoulder significant expense to switch away from one
where it became possible.  Among other things, I doubt that corporate
users would like it, which sorta kneecaps your financial contributions.

 > (where C1' and C2[ab] are cleaner/better/more palatable than C1 and C2).
 > Here you'll want to deprecate C1 and C2, but if your branch is
 > published, you need to keep info about them.  To avoid rewriting
 > history, you may prefer to use something like:

Sure, but this is not a rebase in any sense.  I agree that I want to
be able to substitute a new public history in this way sometimes, but
I would not call it rebase.

Again, what about branches that sprout from C1 and C2?

 > > Doing without the warning will surely screw people.  Even a forward
 > > rebase on the same mainline can run into conflicts.  Any action that
 > > can cause conflicts should not be done without warning the user that
 > > they may need to resolve conflicts.
 > 
 > I fail to see a scenario where such a rebase could introduce a conflict
 > but where the command used isn't one like merge/rebase.  E.g. in a "bzr
 > pull" the above rebases should not have any reason to introduce any
 > conflict: they'd just apply patches following the DAG arrows like any
 > other pull.

If I used the word "pull", I'm sorry.  "bzr pull" never applies any
patches, it just downloads revision data.  What I meant was what
everybody else calls "pull" and bzr calls "merge --pull".  In that
case you can indeed get conflicts that would not have happened without
the rebase.




More information about the bazaar mailing list