This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

new batch of replies (C)



Replies in this message:

	Stan Shebs: History-sensitive Merging Won't Help My Nastiest Merges 
	Zack Weinberg: Merge Scenario

================================================================

Stan Shebs: History-sensitive Merging Won't Help My Nastiest Merges 

     To take an example of something real-life, we have additional
     warning flags not in FSF sources because of the collective
     spoon-gagging response when they were suggested.  Now when Neil
     Booth reorganized option flags into a c-opts.c (a good thing), I
     then had to go and rewrite our local patches to fit this new
     scheme, deleting some code (yay) and moving other bits into
     c-opts.c.  All of this was manual work.

     Sure, it's unreasonable to expect any CM system to somehow divine
     the meaning of an arbitrary change, and then do an arbitrary
     rewrite of a local patch to work with it, but that is what
     consumed the great majority of my time when merging.  It may be
     more reasonable to expect some class of patches to work - perhaps
     a local patch could be made to follow the function it's patching,
     if the function is moved to another file - but my real point is
     that at least for me, a change of CM system would not have had
     much impact on the tasks that took up the largest portion of my
     time.

Right.  There are some things that even clever merging can't help
with.

There is a feature I have considered for `arch' that might help
indirectly, though.

Currently, we generally all work by resolving all conflicts between
commits.   It is an error, for example, if we check-in a file that
contains conflict markers.

I've been considering various ways to formalize the handling of
conflict data with the effect being that you can reasonably commit
revisions with conflicts.  The conflicts are preserved, the revision
marked as containing conflicts, others can check out this revision and
find the conflicts, and (most importantly) if additional merging takes
place, the conflict records are cleanly and accurately combined.

The advantage of this is that you would no longer have to "go it
alone" -- if you have hundreds of nebbishy little conflicts to
resolve, check the whole mess in, and get four people to help with the
work.  Your team of five can use revision control in the usual way: to
coordinate and synchronize their efforts, on in this case, what their
synchronizing _includes_ all the conflict data.a


================================================================

Zack Weinberg: Merge Scenario


This proposal from Zack is long, but insightful, so I've quoted it in
its entirety for reference.

`arch' does not currently have the feature he's asking for, but I
believe the core functionality could be added (as optional behavior
for the `commit' command) with O(30) lines of new code.  In addition,
we'd probably want O(250) lines of new code that can answer simple
queries about "micro-branches".  Finally, we might want another O(250)
lines of code to ensure a convenient user interface to this
functionality. I think this feature will be similarly easy to add to
_any_ modern (e.g. tree-atomic) system with reasonable support for
branching: it is nearly something you can layer on top of such
systems, though for best performance, you might want to intermingle it
a little bit with existing code.

Where arch can shine, for projects that choose to use this feature, is
by making merging these microbranches easier.  My answers to other
questions about merging describe the relevant features.  I'll point
out that microbranches stand in a star-topology relationship to their
primary branch, and repeated back-and-forth merging (as illustrated by
Zach's scenario) is likely to come up.



	Conflict resolution by microbranches goes like this.  We start
	with some base revision of a file.  Let's say Mel was the last
	person to check something in there.

  -- ... -- [MEL] 

	Two other developers, let's call them Dave and Helen, both
	check out the tree and start hacking.  They make changes to
	the same file.  Doesn't matter if they conflict (in the CVS
	sense) or not.  Now they both try to check their changes in.
	CVS says somebody loses the race and has to update, then check
	in a merged version.  This is wrong.  It loses information.
	What should happen is, both checkins should succeed, creating
	two sibling revisions:

 -- ... -- [MEL] --- [DAVE]
                 \-- [HELEN]

	Dave won the race so his checkin gets to be HEAD.  Helen's
	checkin succeeds but it's pushed onto a branch.  It is now her
	responsibility to perform the merge, which gets checked in as
	a *separate* revision:

 -- ... -- [MEL] --- [DAVE]  --- [HELEN+DAVE]
                 \-- [HELEN] --/

	Of course, someone else, let's call him Artie, could have been
	a busy beaver and checked in something on top of Dave's change
	by the time Helen gets round to checking in her merge; then
	the same thing happens again:

 -- ... -- [MEL] --- [DAVE]  --- [ARTIE]
                 \            \
                  \- [HELEN] --- [HELEN+DAVE]

	And then she does another merge and finally gets to win the race. Yay.

 -- ... -- [MEL] --- [DAVE]  --- [ARTIE]      --- [HELEN+DAVE+ARTIE]
                 \            \                 /
                  \- [HELEN] --- [HELEN+DAVE] -/

	Of course this process *really* applies at change set boundaries, not
	file boundaries; so if even one file conflicts between two change
	sets, one entire change set gets microbranched.

	What's the point? you may be wondering.  First, it's always
	possible to recover the exact bits that the original developer
	tested.  GCC has a perennial problem where someone tests the
	source tree at point A, then tests A + their changes, then
	does an update to point B plus their changes, then commits,
	but something in the delta between A and B breaks in
	interaction with their changes -- and what they tested,
	[A+changes], is forever lost.

	Not only is it possible to recover what was tested, but it's
	possible to promote any of the above set of deltas to
	tip-of-trunk.  Suppose Mel comes back and discovers that what
	Dave did is fine, and what Helen did is fine, but what Artie
	did is broken -- she can just tell the system "make
	[HELEN+DAVE] tip of trunk" and boom, the broken changes are on
	a branch; other people can move forward.  Artie can fix his
	bugs later.  (In other words, backing out changes is really
	easy, and putting them in again once they're fixed is also
	easy.)

	And finally, because all of the merge participants are present
	and recorded in the version history, it's possible to use a
	smarter algorithm to execute the merges than would be
	available with CVS's semantics.  This is where your example
	fits in, Mike.





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]