Fixing rebase rather than avoiding it

Stefan Monnier monnier at iro.umontreal.ca
Sat Mar 6 20:07:52 GMT 2010


> Also, be aware that you're on a slippery slope, whose bottom is
> "commit == tree, all else is modifiable annotation".  This is
> unsatisfactory, because you end up losing all sense of history.

Indeed, "commit == tree" can't be the whole story, since you
otherwise lose track of the history.

> 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.

>> 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 <--------------+

It's not the same as a "merge" because it generates more than
one commit.  Notice that this can be done without rewriting history.
 
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 <-+

(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:

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

and mark C1,C2,C3 as obsolete.

>> For typical uses of rebase (where it's used as an alternative to merge),
>> such a warning would just be annoying.  But, I could live with it
>> ;-)
> 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.

>> I'm not completely sure that's true.  But yes, as mentioned, we'd
>> probably want to keep track of the intention behind the arcs.  This
>> is not completely new, tho: Bzr already has the notion of "leftmost
>> parent" for very similar reasons.
> Implementation-wise it would be quite different.  git also has a
> notion of leftmost parent, as Teemu demonstrated to Óscar.  This is
> just an artifact of the ordering property of vector indicies.

Yes.  It would need to be a "designed" feature, rather than some
accidental result.


        Stefan




More information about the bazaar mailing list