On 10/5/07, Jack Repenning <jrepenning@collab.net> wrote:
> There was some discussion, a while back, about overlapping change
> sets. A perhaps over-brief summary seems to be:
>
> > Several people wanted them well-managed, but Ben didn't think the
> > problem was worth attention, so none was given it.
Well, this isn't exactly fair. :-) It's not that the problem isn't
worth attention -- I would *love* to see it. But you have to take
small steps. The design doc explicitly states overlapping changelists
as a non-goal:
A number of people ask "but what if two different changes within a
single file belong to different logical changes?" My reply is:
either "tough luck" or "don't do that" or "checkout a separate
working copy". My feeling is that trying to create a UI to
manipulate individual diff-hunks within a file is a HUGE can of
worms, probably best suited for a GUI. While I wouldn't rule it
out as a future *enchancement* to a changelist feature, it's
certainly not worth the initial effort in the first draft of
changelist management. Overlapping changelists do occasionally
happen, but they're rare enough that's it's not worth spending 90%
of our time on a 10% case -- at least not in the beginning.
IIRC, I don't think anyone disagreed with my scaled-down goals at the
outset, other than cmpilato. If folks would like to work on
hunk-management for overlapping changesets in 1.6, that would be super
cool! It's a big task.
> Some details of the implementation actually prevent overlaps (for
> example, a given target can be in at most one changelist). But
> overlaps are not completely prevented, and the system behavior when
> they do arise is very surprising.
I think there's a misunderstanding here: overlaps *are* completely
prevented. As you say: a path can only belong to one changelist at a
time. The confusion here comes from the unusual case of adding a
directory to a changelist: what does that mean? Your (totally
reasonable) assumption is that it's a depth-infinity operation. The
reality is that it's a depth-0 operation, just as with files. The
only reason we allow directories to be members of changelists is so
that we can commit property-changes to them, just like when we do 'svn
commit -N dir'.
From this one miscommunication, we get most of the confusion:
> $ svn changelist l1 src src/foo.c
> $ svn changelist l2 src/bar.c
>
> Question: is bar.c in list l1? Opinion differs:
>
> $ echo >> src/bar.c
>
> $ svn stat
> --- Changelist 'l1':
> src
> src/foo.c
>
> --- Changelist 'l2':
> M src/bar.c
'svn status' is correct. Changelist l1 has excactly two depth-0
members, changelist l2 has one depth-0 member.
> $ svn diff --changelist l1
> Index: src/bar.c
> ===================================================================
> --- src/bar.c (revision 2326)
> +++ src/bar.c (working copy)
> @@ -21,3 +21,4 @@
> }
> sleep(1);
> }
> +
This is a bug, no doubt! On nearly every command, we implemented the
--changelist switch as "here's a bunch of paths, put them in your list
of targets". It's just a shorthand for writing all the paths out on
the commandline.
What you've done to trigger this bug is add a directory to the
changelist -- something we've almost never tested. And now 'svn diff'
is treating the directory as a depth-infinity target, rather than a
depth-0 target. Oops. This needs to be fixed.
> $ svn ci -mx --changelist l1
> svn: Unknown changelist 'l1'
>
> "Unknown"? Even "stat" at least knows of this changelist, though it
> shows no changes therein, what's this "unknown" business? OK, let's
> try:
>
> $ echo >> src/foo.c
> $ svn ci -mx --changelist l1
> Sending src/foo.c
> Transmitting file data .
> Committed revision 2329.
>
> OK, so "ci" can make the intended sense of a changelist when there
> are changes there, though not so much when they're not.
There's sort of a bug here, and sort of not.
If you had typed 'svn commit src src/foo.c', and there were no local
edits to commit, I would expect nothing to happen. Commit returns 0,
it's a no-op.
However, it looks like you found a buglet... I think the existence of
the directory path in the changelist *and* lack of changes to commit
caused the commit codepath to error weirdly.
> Then there's the behavior of auto-removal from a changelist. If you
> commit a change, the item is removed from any change list where it
> might reside; good so far. But if you commit the changelist, and it
> contains some unmodified objects, they are not removed from the
> change list.
Yes, the design doc explictly states that "being a member of a
changelist" and "having local mods" are completely orthogonal things.
They have no effect on each other.
> I can think of some workflows where that makes sense,
> like "I need to make a related change to all these files, but I'll
> commit them in chunks, say because I like to commit once a day." But
> I could also tell that tale as "I need to make this change to all the
> files in this directory, so I put the directory into the change list,
> but hey, it never gets autoremoved because I'm not actually changing
> the directory." The feature implements a certain workflow, but not
> others, yet there seems no guidance on what to expect.
Again, the confusion here is that you expect a
directory-in-a-changelist to be a depth-infinity thing. And
apparently we're not perfectly enforcing that idea in 'svn diff' or
'svn commit'; I'll investigate this week.
That said, I think it might be nice to add depth-infinity directories
to changelists -- very useful. But strangely, it never came up in the
months of design discussion, and thus was never implemented... :-/
In the meantime, we need to make the depth-0 directory aspect really
clear.
Thanks for testing! I know that dlr, jerenkrantz and I have been
using this feature for 6 months, but apparently you're the first
person to actually try to add a directory to a changelist. I'll fix
these two bugs and add tests.
As for guidance on the feature overall -- until the book documents it,
here's a complete summary of the UI:
1. add path(s) to a CL:
svn cl CLNAME foo.c bar.c baz.c
2. remove path(s) from whatever CLs they each belong to.
svn cl --remove foo.c bar.c baz.c
3. move path(s) from CL1 to CL2.
svn cl CL2 foo.c
4. undefine a CL all at once (by removing all members)
svn cl --remove --changelist CLNAME
5. rename a CL
svn cl NEWNAME --changelist OLDNAME
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Oct 8 17:02:54 2007