Karl Fogel wrote:
> On 1/16/07, Daniel Rall <dlr@collab.net> wrote:
>> The typical case where I require overlapping change sets is for a
>> refactoring opportunity or requirement encountered while working on
>> some other feature. For example, while working on JavaHL's logging
>> code, I suddenly realize that in an error situation I need to throw a
>> specific type of exception, for the case where the logging code is
>> invoked from JavaHL's the SVNAdmin class instead of its SVNClient
>> class. Unfortunately, previous to r22985, JavaHL's exception factory
>> code would only throw ClientException. So I refactor the code to
>> allow me to specify the exception type to throw. Unfortunately, both
>> the logging code and the exception factory code are in the JNIUtil C++
>> class! So the change that I started making first needs to be
>> committed second, and depends on another change in the same file I
>> completed while working on the initial change.
>
> This is the common case for me, too. I often have multiple changesets
> running at once (I mean conceptual changesets -- not using the
> "changelist" featue, just squirreling away patches and doing the CMike
> workaround). This is usually because while working in a file to solve
> problem A, I encounter problem B, and then in the course of solving
> B encounter C, etc. Naturally, A, B, and C all deserve separate commits.
This is also my work flow.
Are you guys familiar with the tool called "quilt"?
http://savannah.nongnu.org/projects/quilt/
http://www.suse.de/~agruen/quilt.pdf
It is *almost* a very cool tool, but in combination with SVN I think it
would be a very good model for solving the changeset problem in a more
general and more natural way than the changelist feature that is being
discussed.
I haven't worked very much with quilt, but I'll nevertheless try to
provide a brief sketch of how it works followed by how an SVN + quilt
system could work.
<brief-sketch-of-quilt>
Quilt manages an ordered list of N named patches (aka changesets). At
any given moment, the first n <= N patches are applied to your working
copy and the top applied patch is active:
clean-up-docs.diff <- this patch is not currently applied
fix-segfault.diff <- this patch is not currently applied
add-pool-argument.diff <= the top applied patch
replace-array-with-map.diff <- this patch is applied
error-refactoring.diff <- this patch is applied
Quilt talks about a stack of patches, with commands "quilt push" and
"quilt pop" to apply patch n+1 or un-apply patch n, respectively. These
commands record what is the new "top" patch and by default they refuse
to apply a patch that does not apply cleanly. Even if you have edited
the working copy, you can still push/pop patches as long as they apply
cleanly.
What you can do with quilt is manage and modify patches very dynamically.
If you want to improve a patch before committing it, all you have to do
is bring it to the top of the stack, edit the WC, then type "quilt
refresh". This command changes the top patch to include its old
contents plus the changes to the working copy.
You can create a new patch at the top of the stack by typing "quilt new
<patch-name>". The new patch starts out empty.
There are lots more commands that do more-or-less obvious things: "quilt
diff", "quilt import", "quilt delete", etc.
</brief-sketch-of-quilt>
quilt has one very annoying failing: you have to tell it what files you
want to modify as part of a patch *before* modifying them. Otherwise it
gets hopelessly confused in a way that is awkward to fix.
Wouldn't it be cool if svn would support the following sequence of actions:
$ svn co $URL
Start editing some files, then realize that there's something you want
to change before your half-done changes.
$ svn newpatch "myfeature"
$ svn refreshpatch
$ svn poppatch
At this point your WC is in virgin state again, with a patch called
"myfeature" tucked away in the .svn directories somewhere. Now you
start editing files to implement the new new pre-feature.
# Verify that pre-feature works:
$ ./run-tests
# Pack it up as a patch, not yet committed:
$ svn newpatch "prefeature"
$ svn refreshpatch "prefeature"
# Apply the half-finished "myfeature" patch on top of "prefeature":
$ svn pushpatch
At this point you have two live changesets, both applied to the WC. The
top (active) patch is "myfeature". You edit files to complete the
implementation of "myfeature", then
# Verify that the current WC is not broken:
$ ./run-tests
# Store the complete changes to the "myfeature" patch:
$ svn refreshpatch "myfeature"
# Get ready to commit upstream:
$ svn poppatch --all
# Optionally update before commit:
$ svn update
# Commit "prefeature":
$ svn pushpatch
$ svn commitpatch -m "Pre-feature description"
(this would probably mark your "prefeature" patch as obsolete)
# Commit "myfeature":
$ svn pushpatch
$ svn commitpatch -m "My feature description"
Some other things that would be very cool:
- Allow commit messages to be stored with patches, and edited whenever
the patch is active (quilt supports this).
- Allow multiple patches to be committed at once.
- Allow the order of patches to be swapped, provided they don't conflict.
- Allow a patch to be split in a sensible way. (For example, apply all
of the combined patch, then undo the things you don't want in the first
patch.)
- To synchronize a branch with trunk, download the missing changesets
from trunk into your patch set, then work through them one by one until
they all apply cleanly, then commit them all in one commit to the branch
a la svnmerge.py.
The amazing thing is that quilt is implemented as a bunch of shell
scripts--something like 5000 lines total. It really isn't rocket
science. (About the only technology we would need to get started with
this would be a format for storing diffs that include property changes.)
And quilt would be so much nicer if it were coupled with an SCM.
You might think that quilt is just a poor man's distributed SCM. But
the flavor of working with it is quite different, because patches are
very mutable until the moment that they are committed upstream. Try to
imaging all of the branching and merging stunts you would have to do to
"retroactively" improve a commit using a distributed SCM. With quilt it
is just a few trivial commands.
One key advantage of the quilt way of working compared to the changelist
model is that quilt recognizes that patches have to be kept in order to
be well-defined. Patches don't, in general, commute. If you
acknowledge the fact that patches' order has to be preserved, then it
becomes trivial to support changesets at a finer granularity than
file-level.
Michael
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Thu Jan 18 00:51:42 2007