[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Issue 2897 revisited. Really.

From: Karl Fogel <kfogel_at_red-bean.com>
Date: 2007-11-28 23:07:24 CET

"Ben Collins-Sussman" <sussman@red-bean.com> writes:
> The problem here is how to deal with long-lived feature branches that
> are kept up-to-date with trunk, then eventually re-merged back to
> trunk. In our simple example, we imagine a scenario where the user
> merges /trunk:1-100 to the branch and gets some conflicts. She then
> resolves the conflicts, and commits r101 to the branch. After a few
> more branch commits, she merges back to trunk. What should our
> merge-tracking feature do?
> Mark (and others) have pointed out that the Big Problem here is "what
> to do about r101". It contains all of the /trunk:1-100 changes and
> *also* some branch-specific conflict-resolution. Our current
> machinery either includes or excludes entire revisions, which poses a
> dilemma. If we merge r101 back to trunk, we'll get 100 revisions of
> repeated-merge errors. If we don't merge r101 back to trunk, then we
> lose the critical conflict-resolution changes (which are likely needed
> to make other branch-changes apply correctly to trunk.) Our current
> code would include r101; when Kamesh is done with his issue-2897
> branch, our code would exclude r101. Both behaviors are wrong... or
> at least sub-optimal, and lead to problems for the user.
> So what should a proper merge-tracking feature do? It should merge
> *just the conflict resolution changes* back to trunk. In other words,
> we need to stop treating revisions as atomic units -- the proper
> solution is to apply just the "correct" part of the revision. As
> DannyB explained in IRC, our merge code should take the r101 change,
> *subtract* the /trunk:1-100 changes from it, and whatever's left over
> is the correct patch to apply to the trunk.
> Yes, this is hard, but it's correct. We'll need new APIs for this
> sort of thing.
> DannyB also pointed out that sometimes other version control systems
> cheat in this area: that merging the branch to trunk causes an
> "automatic" commit (even if there are conflicts!), and then the user's
> conflict resolution changes are an extra commit on top of that. This
> guarantees that the changes aren't blurred together into one revision.
> This is possibility for us, if we don't want to go through the work of
> patch subtraction.

Yes. This latter solution is exactly what I proposed to glasser in
IRC yesterday (transcript at the end of this mail).

I think issue #2897 is really two separate issues rolled into one.
Disentangled, they are:

   1) When you merge a BRANCH to TRUNK, don't merge back revisions
      which had previously been ported from TRUNK to BRANCH.

   2) Don't lose conflict resolution work (where "lose" can mean
      "mistakenly lump it in with purely merged changes").

My understanding -- based on nothing but instinct, and perhaps totally
wrong -- was that the issue #2987 branch is to solve (1), because
that's a prerequisite to solving (2). I'm reviewing the change that
solves (1) partly in order to understand what we have to do for (2),
though I hadn't thought we'd do (2) for 1.5. We could, though.

However, your mail makes me wonder if we all have the same
understanding of what the problem is. I'd love to do (1) and (2), and
both seem feasible. I'm not sure they should be thought of as the
same issue, though.

> I don't want to derail all the work Kamesh and Karl have been doing in
> the branch, but I really feel like this is the Correct Solution -- and
> it's going to involve a (little bit) of breaking of the walls we've
> made for ourselves. :-)

So here's the conversation I had with glasser:

  <kfogel> I know a way to solve the "we don't record
            conflict-resolution-work" problem.
  <kfogel> It's not so hard, really.
  * kfogel waits for someone to notice his hubris before continuing
  * glasser coughs
  <kfogel> simple
  <glasser> We could just not have conflicts
  <kfogel> when you update and the result is a conflicted file, or
            even just a merged file (whatever -- I'm going to hand wave
            on some details, as you'll see, that won't matter).
  <kfogel> anyway:
  <kfogel> when you update and the result is a conflicted file, then
            record the conflicted version of the file as its own
            text-base somewhere. When you resolve, record *that*. When
            you commit, it needs to result in two consecutive new
            revisions: one for conflicting, and one for resolved. They
            should appear simultaneously, ideally.
  <kfogel> That's a very compressed description, but you probably get
            the idea.
  <kfogel> the point is that the post-update-but-pre-resolution work
            state *can* be saved.
  <glasser> That's vaguely what I was thinking above, just one problem
  <glasser> will you actually be able to merge the resolving diff?
  <kfogel> (oh, I didn't really read the backscroll, sorry)
  <glasser> I was only thinking it in my head :)
  <kfogel> sure, by definition you will
  <glasser> It'll be a diff from conflict-markers to correct
  <kfogel> it's a diff2, after all.
  <glasser> and how do you apply that to happy trunk?
  <kfogel> you never need to do that
  <kfogel> no one else ever *has* the conflicted version (unless they
            explicitly request it, of course, in which case it's just
            like any other version)
  <kfogel> the two steps are:
  <kfogel> - happy, ignorant trunk -> conflicted state
  <kfogel> - conflicted state -> resolved
  <glasser> how does step one happen?
  <kfogel> it's the first half of the new dual commit
  <glasser> Or, um, let's step back a moment
  <glasser> I think what we're talking about is:
  <glasser> (a) Change r42 is made on trunk.
  <glasser> (b) The change is merged to branch B; this has conflicts
            which needs to be resolved
  <glasser> (c) We try to merge everything from B to the trunk.
  <glasser> Now, in your scheme, I think you're saying that at time (b)
            there are two commits to B: one in "conflicted" form which
            is also what adds the r42 mergeinfo
  <glasser> and one that resolves it
  <kfogel> uh, yes
  <glasser> Right?
  <kfogel> I think that's what I'm saying, yeah.
  <glasser> OK, so now it's (c) time
  <kfogel> oh
  <kfogel> wait
  * glasser waits
  <kfogel> I haven't thought about mergeinfo, but I think what you say
            above is right.
  <glasser> Let's say those two commits to B are r70 and r71.
  <kfogel> ok
  <glasser> We don't merge r70 back to trunk because it is "reflected"
            (that's the feature that kameshj is doing now)
  <glasser> so we try to merge r71 only
  <glasser> now what is r71?
  <kfogel> oh
  <kfogel> okay
  <glasser> r71 is basically a delta from conflict to no conflict
  <glasser> but on trunk there is no conflict!
  <kfogel> yes, merge tracking raises an issue that I haven't pondered
  <kfogel> since we're not going to do this for 1.5, and it's more
            important that I get on Kamesh's truck, let's just remember
            this line of thinking for the future.
  <glasser> right
  <kfogel> I'd be more verbose but I just got a phone call.


To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Nov 28 23:07:38 2007

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.