Order of merges and the appearance of the revision history

John Arbash Meinel john at arbash-meinel.com
Tue Apr 24 18:28:12 BST 2007

Joseph Wakeling wrote:
> Something that's started to bother me is that revision history in bzr is
> dependent not just on what patches are in the system but also on what
> order merges and pulls happened.
> I've attached a simple little shell script to show what I mean.  It
> creates two divergent branches (1 and 2) and then clones each into a and
> b copies.
> 1a merges from 2a, and 2a then pulls from 1a.
> 2b merges from 1b, and 1b then pulls from 2b.
> Now, if we look at either an a branch or a b branch with bzr viz, the
> revision history is topologically identical, but it's displayed
> differently depending on the order of the merge.
> Worse, bzr pull won't let me pull from a b branch to an a branch,
> despite the fact that the _code_ is identical and so, topologically
> speaking, is the revision history.
> I wonder if anyone could give some insight into why this is and what
> purpose it serves (if any).
>     -- Joe

Attached is a graph showing your revision history, and labeling where
each of the branches is at (at the end of your script).

The biggest thing is that merging revision A => B is not identical to
merging B => A. You can argue that they are topologically the same, but
in reality there is a user difference (several, in fact).

1) *I* committed one revision, whereas *you* committed the other one.
(b1a_4, versus b2a_p)
So at a minimum they have a different committer id and timestamp.

2) I may have resolved conflicts in a different way. In your particular
case there were no conflicts, and you happened not to make any other
changes. However, often when merging, there are non-textual conflicts.
Meaning the merge is "clean", but the tree doesn't work. Because of a
conceptual change.
As an example:
 if b1_3 changed the foo() function to take a new parameter, but
 b2_3 updated bar() to call foo().

After merging, there would be no *textual* conflict (because the changes
happened in different files), but the tree would still be broken. (It
would not compile, run, tests would fail, etc.)

By having the extra "b1a_4" and "b2a_4" commits, we are giving you an
opportunity to have your tree *work* before you commit.

In many other systems there is no "merge + commit" doing the "merge"
automatically commits if there are no textual conflicts. We don't.

3) They are only topologically the same if you consider the parents
"equal". This is another point of discussion, but bzr specifically does
not. The first parent is different from the others. Because to humans, I
have a base, and I do a merge, and I review the changes (against the
*base*), and then I commit. So the changes I am committing are the
changes *against base*, not against the merge.

4) It gives a "rollup" commit. Imagine that b2_3 was actually a series
of commits which implement a given function. After merging and
committing b1a_4, you can do something like "bzr log --short" which
could show you:

  1 A first file
  2 A second file
  3 My best friend
  4 Merge from b2a [merging feature foo]

So the idea is that you can have a nice simplified view of the changes
in the project, without getting cluttered by the details of every change.

If you look at the bzr.dev mainline and do "bzr log --short", and
compare that to "bzr log --long".

In '--short', you can see a nice simple series of the changes that have
been happening.

 2440 Canonical.com Patch Queue Manager 2007-04-21
      (John Arbash Meinel) Fix bug #105479: properly handle moving a
directory with children that have been added, renamed, removed

 2441 Canonical.com Patch Queue Manager 2007-04-23
      (robertc) Fix bugs 107656 and 50408 by creating multiple help
indices and cross referencing between them when user help requests are
ambiguous. (Robert Collins)

 2442 Canonical.com Patch Queue Manager 2007-04-23
      (robertc) Add the infrastructure for having C extension modules
based on pyrex in bzrlib. (Robert Collins).

 2443 Canonical.com Patch Queue Manager 2007-04-23
      (robertc) 'bzr help urlspec' - new topic giving help on http://,
sftp:// etc. (Goffredo Baroncelli)

 2444 Canonical.com Patch Queue Manager 2007-04-23
      (robertc) Mark bzrlib.tests and bzrlib.tests.TestUtil as providing
assertFOO helper functions by adding a __unittest global attribute.
(Robert Collins, Andrew Bennetts, Martin Pool, Jonathan Lange)

 2445 Canonical.com Patch Queue Manager 2007-04-23
      (robertc) Update doc/server.txt and the port the smart server
listens on. (Robert Collins, #107125, #98918)

 2446 Canonical.com Patch Queue Manager 2007-04-23
      (robertc) bzr --fixes support to allow recording of bugs that are
fixed by commits. (Jonathan Lange, James Henstridge, Robert Collins)

 2447 Canonical.com Patch Queue Manager 2007-04-23
      (Andrew Bennetts) Make RemoteBzrDir.open_workingtree raise
NoWorkingTree instead of NotLocalUrl when appropriate.

Now try that again with "bzr log --long -r 2440..2447". And you have
pages and pages to sort through to figure out what changes have been

I can understand that there are "trivial" cases that seem like they
would be better handled by having the merge+commit be considered
symmetric whether you merge me, or I merge you.

But there are farther reaching effects of having the topology be
distinct. And when you get into more complex cases, it generally makes
things easier to understand.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: test_graph.png
Type: image/png
Size: 6303 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20070424/4635f6b8/attachment.png 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test_graph.dot
Type: application/octet-stream
Size: 935 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20070424/4635f6b8/attachment.obj 

More information about the bazaar mailing list