On Dec 4, 2007 7:45 PM, David Glasser <glasser@davidglasser.net> wrote:
> I promise that explaining today's work will be the first thing I do
> after getting to work tomorrow (9AM Pacific)...
The main idea behind yesterday's work is this observation: the action
"merge everything from branch A to branch B" actually could mean two
entirely different things:
* Take all the changes that have been committed on branch A and make
the same changes on branch B, ignoring those that have already been
moved over. ie, "move the changes", or "pick all the unpicked
cherries (cherry-harvest?)"
* Take the contents of branch A, which already represents a
combination of all the work on branch A and branch B, and make
branch B have the same contents. This is what happens when you're
"done" with a feature branch, have already reconciled trunk changes
with it, and are ready to load the feature into trunk. In a
high-level sense it's really a rename or rebase operation: kind of
like "svn rm url://B; svn cp url://A url://B".
In fact, according to the svnbook, the preferred way to maintain a
feature branch (pre-1.5) is to use commands of the former kind to
cherry-pick changes from trunk to feature branch; once the feature is
done on the feature branch *and* the feature branch has all of the new
work from trunk merged to it using commands of the first kind, you
make a trunk checkout and use a two-URL merge to do a second-kind
merge into trunk, and commit that.
There are two annoyances with merging a feature branch back to trunk
this way in SVN today:
(1) The command you're supposed to type is essentially
$ svn merge url://to/trunk_at_1234 url://to/branch_at_1234 wc-of-trunk-1234
When this is the operation you're trying to do, the first URL really
is redundant with the wc. Having to type out both makes this sort of
operation more difficult for the user. (Note that before 1.5,
"svn merge URL [WC]" was meaningless.)
(2) It's important that the feature branch you're merging into your
trunk WC really does represent all of the trunk development in WC,
or else you will accidentally unmerge some of that development. We
could check this with mergeinfo, but at the moment we don't.
It's my belief that for "merge feature branch back to trunk", you
really *do* want to be doing a merge of the second kind, not of the
first kind. That is, if you have a feature branch and have kept it up
to date with trunk, and have already tested that your feature works,
you just want to directly put the exact tree you have tested onto
trunk, by taking one diff and applying that. You *don't* want to
"reverse cherry-pick": that is, you *don't* want to say "find all the
commits I did on my feature branch to create my feature, and apply
them one at a time to the current trunk". That is very unlikely to
work; what it is likely to do is make you resolve the same stupid
conflicts over and over for every single revision that is
cherry-picked back to trunk. (svk does this in its "unlumped" merge
modes; it is frustrating enough that I just gave up on using
"unlumped" merge. There is nothing that can make you hate your
version control system as much as sitting there making the same
one-line change to code you haven't touched in weeks over and over
again during one merge operation.)
So! The point of the whole-branch-merge branch is to add support for
"whole-branch merges" in a way that requires the user to track less
information. That is, we're taking a previously-recommended merge
operation and letting Subversion fill in some of the parameters for
you, which is really what 1.5 Merge Tracking is all about.
This will support "merge feature branch back to trunk" in a different
way from #2897. We essentially are redefining #2897 to specifically
be about bidirectional *cherry-picking*, and considering that to be a
1.6 feature. (Some analysis of other systems, such as git and
mercurial, make me believe that they do not handle bidirectional
cherrypicking in an effective manner either.)
We decided to start by implementing an operation that works only in a
special case (which is carefully checked) and throws an error
otherwise; the idea is that we can then (before or after 1.5 release)
generalize it by offering support for some of the things that start as
error cases.
The specific case we're starting by handling (and the bulk of this is
done; we're just ironing out bugs) is:
* The working copy you're merging into is a pristine, single-rev,
unswitched checkout: ie, it's something you could get as a fresh
checkout of some URL@REV
* The branch you're merging from has (according to mergeinfo) all of
the changes on that URL up to REV integrated (using cmpilato's
merge source normalization / location segments)
In that case, you can just type
$ svn merge url://to/feature-branch
and it will do the right thing. We will also make it add mergeinfo
for this merge.
If this works, I think we can happily defer #2897 to 1.6.
Note that so far, nothing for this feature requires sqlite. Our
branch is based on my branch which adds extra metadata to FSFS
noderevs to allow for efficient mergeinfo queries of the kind
currently made.
(As far as sqlite goes, if we do decide to merge this feature branch
to trunk, I would like us to at least temporarily stop using sqlite
for mergeinfo queries, though we can leave the indexing code there for
a little bit if we want. This will cause some tests to fail: these
tests rely on mergeinfo queries on nonexistent paths to not throw an
error, which I think is incorrect. Even if we end up later
reintegrating sqlite because we later need to make more sophisticated
queries, we should fix the bugs that are causing us to send queries on
nonexistent paths!)
It seems that cmpilato is also working on a similar feature to this
branch. I'm not exactly sure how it compares to what we're doing.
--dave
--
David Glasser | glasser_at_davidglasser.net | http://www.davidglasser.net/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Dec 5 20:06:51 2007