Non-expected conflict

Gustavo Niemeyer gustavo at niemeyer.net
Wed Mar 22 15:54:26 GMT 2006


> Gustavo Niemeyer wrote:
> | Running bzr blame on the current revision (79) of branch-chris
> | still shows that Chris is using Gustavo's code:
> 
> Giving bzr blame output isn't relevant, because we don't use this
> information for doing a merge (except weave merge, which is not the
> default and is broken in bzr.dev).

It is relevant, because it explains the situation, and why I
expect that the tool *should* be able to handle it. One of
the most important parts of a distributed revision control
system is the merge algorithm. If you get conflicts just by
merging from a branch that merges from you, then having
multiple branches becomes a pain, not an advantage.

> It would be much more helpful to provide excerpts from the THIS BASE and
> OTHER files, because those are the inputs to the merge algorithm.

Here's an excerpt of "diff -u test.BASE test.OTHER":

   if __name__ == "__main__":
  -    status = main()
  -    sys.exit(status)
  +    runner = os.environ.get("TEST_RUNNER", "unittest")
  +    runner_func = globals().get("test_with_%s" % runner)
  +    if not runner_func:
  +        sys.exit("Test runner not found: %s" % runner)
  +    runner_func()

Which is surprising. As I've shown in the previous mail, branch-chris
merged in revision 75 the changes made in branch-gustavo on revision
58, so that should be the base, at least, and my changes should be
included in the "minus" part above.

This is "diff -u test.OTHER test.THIS":

   if __name__ == "__main__":
  -    runner = os.environ.get("TEST_RUNNER", "unittest")
  +    runner = os.environ.get("TEST_RUNNER")
  +    if not runner:
  +        runner = "unittest"
       runner_func = globals().get("test_with_%s" % runner)
       if not runner_func:
           sys.exit("Test runner not found: %s" % runner)

That's precisely the change I did in revision 65 of branch-gustavo,
and what bzr should understand as the code to stay there without any
conflicts.

> I think comparison of THIS, BASE, and OTHER would show that the
> algorithm is performing reasonably well.

I now belive that the alogrithm is doing the wrong thing in two
different ways:

1) Got the wrong base

2) Isn't considering history, which is one of the important
   aspects that a distributed revision control has to implement
   to make the branch-hell manageable.

>   You could also try using
> --reprocess for merging, which should reduce the conflict regions to:

As you can see above there isn't another way that would avoid the
conflict region, if bzr gets those bases and uses non-weave merging.

> Here's what I think this is happening.  I think your merge history can
> be simplified for these purposes like so:
> http://aaronbentley.com/pastegraph.cgi?n=198

Nice tool!

[...]
> Or, to make a long story short, it's a criss-cross merge.  R61 should
> have been chosen as the base.  But if it had been, you would still get
> conflicts here because R61's text for this region won't match Gustavo's
> or Chris'.

Interpreting the graph-ancestry output and the information above, what
happens is, g62 merges c73, c75 merges g61, g73 merges c79, and gets
conflicts for changes done in g58.  That's basically what CVS does
when merging branches, except that you write down the last merge in
the log and you are aware about what conflicts to expect since you're
selecting the merging base by hand.

> Which is exactly where weave merge would rock, if it wasn't busted.

So far I've been advertising that as something that bzr was able to
do, and was hoping that we wouldn't face that kind of problem when
working with branches.  Whenever I touch a piece of code I know I'll
get a conflict on the next time I merge from someone that merged
from me.  How to avoid that? Simple.. use a central integration branch
and always discard branches after they get merged in the integration
branch.  But then, Subversion starts to look as an interesting
competitor.

-- 
Gustavo Niemeyer
http://niemeyer.net




More information about the bazaar mailing list