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

Re: Subversion "labels" vs. "tags"

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: 2005-06-02 15:24:47 CEST

Tim Hill wrote:
> ok, let's consider patch propogation.

Cool. Thanks for taking the time to present this use case.

Now, as usual, I'm going to go through it and comment. Well, OK, I'm going to
push the case for the present Subversion tags mechanism a bit, but I think I
need to push a bit in order to draw out a good argument from you. :-) I hope
you don't mind.

Oh, and let me make it clear that I don't necessarily think revision-alias
labels are a bad idea; I'm still just trying to fully understand the rationale
for them.

By the way, I don't know, but it might help a bit to know what your background
is. For example, are you accustomed to some particular version control system
other than Subversion, or do you have wide experience, or what? One thing that
makes me wonder is in the next sentence where you refer to your mainline build
as the "main branch"; if you were accustomed to Subversion you would have
called it the "trunk".

> I have a mainline build ("main"
> branch) and a release branch ("rel1") that just takes bug fixes for a
> released version of the product. The mainline undergoes cycles of
> dev/test/stabilize, and at each stabilization point a "stable" tag is
> created so that the last stable build is easily accessible.

OK, I imagine that's a common scenario.

> A bug is found in the mainline in "foo.c". It is tracked in a defect
> tool, fixed in the mainline, checked-in, and undergoes the normal
> dev/test/stabilize process. Product support then decides that the bug is
> serious enough that it should be fixed in the "rel1" branch also, ready
> for the 1.1 release.

OK.

> How do I merge the fix into the "rel1" branch? Specifically, which
> revisions off the mainline do I compare to get the changes necessary to
> push into "foo.c" in the "rel1" branch?
>
> There are actually four points in time that are significant (working
> backwards):
> [1] The rev# of the latest stable build of the mainline branch. Call
> this rev# STABLE.
> [2] The rev# where the fix to "foo.c" was checked into the mainline
> (that is, when the defect was marked as fixed). Call this rev# FIXED.
> [3] The rev# where the last change to "foo.c" was made prior to FIXED.
> Call this rev# PREFIXED.
> [4] The rev# where "rel1" was branched off of the mainline. Call this
> rev# REL1.
>
> What I want to merge into the head of "rel1" is: DIFF foo.c -r
> PREFIXED:FIXED. However I also need to examine DIFF foo.c -r
> REL1:PREFIXED to make sure that the fix does not depend upon changes
> made to foo.c between REL1 and PREFIXED. Note that I cannot take DIFF -r
> PREFIXED:STABLE since other changes may have occurred in foo.c between
> FIXED and STABLE (I'm assuming "rel1" has its own testing/stabilization
> cycle).

OK.

> How do I locate and use the various rev# values needed? STABLE is
> available in the "stable" tag noted above, so that's easy (but not much
> use in this scenario).
>
> Neither FIXED not PREFIXED are available via tagging.

Well, that depends whether you tagged them! (Actually I wouldn't expect you to
have tagged PREFIXED - see below - but you suggest below that you would have
labeled FIXED if you had labels, so I suggest you would have tagged it if you
only have tags.)

> Assuming I'm using
> the recommended best practice of marking defect #s in the message log, I
> will need to manually examine the log to extract the rev# from the log
> messages.

Well, actually what you need to do is find the revision number in which the fix
was made, if you haven't tagged it. To find the revision number, you could
look through the log messages, or perhaps you can look in your bug tracker, or
perhaps you have it in a revision property as I mention under your point (b)
below. In this project we try to close bugs in the issue tracker with a
comment like "Fixed in r1234.", so the information is fairly easy to find manually.

> REL1 is available via the --stop-on-copy switch, but this is not
> available in the DIFF or MERGE commands, only LOG. So , again, I have to
> do a manual scan of the log to obtain the rev#.

Again, you only have to do a manual scan if you haven't tagged it. I would
expect that you would have tagged it. At the time when you started your "rel1"
branch you would have done:

svn copy . $BRANCHES/rel1 # start a "rel1" branch
svn copy $BRANCHES/rel1 $TAGS/rel1-start # label your "rel1" starting point

and then you would start to modify the "rel1" branch, and you would tag various
release candidates ("rel1-rc1" or whatever) along the road towards finishing
it. When finished, you would tag the final version of it ("rel1") and delete
the branch.

svn checkout $BRANCHES/rel1
# modify stuff; it seems stable enough to release
svn cp . $TAGS/rel1-rc1 # tag a release candidate
# now it's been tested and is definitely stable and complete
svn copy . $TAGS/rel1 # tag the final version of it
svn delete $BRANCHES/rel1 # the branch is no longer needed

At least that's roughly how we do it in this Subversion project. Actually, we
haven't been tagging the start of the branch, but we could and would do if we
found it useful.

> This is a lot of work for what is not an unusual scenario. How can it
> made less manual (read: less error-prone)?

> (a) I could add lots of tags. If FIXED was available as a tag, that
> would work. But creating a tag for *every* defect fix seems excessive,
> even if tags are cheap. And who will remember to do this?

Umm... it'll be fun to see if you can convince us that the same comments don't
apply to revision-alias labels :-)

> More
> importantly, how do I locate PREFIXED? This is a *relative* rev# and is
> conceptually related to the COMMITTED rev#, but with an arbitrary
> starting point.

Actually, this is easy if you are working with actual revision numbers either
manually or in a programming/scripting language: you can just subtract 1. You
can see that this is correct by thinking about the difference between foo.c in
revision PREFIXED and revision (FIXED-1): by definition, there is no difference.

If you are working with a tag, then you can't at present get Subversion to
calculate the previous revision for you. That is a deficiency which I admit is
important in this scenario.

There was a proposal for adding a syntax for doing this within the
revision-number argument: something like "-rHEAD-1" or "-r{2005-05-31}-1" would
mean the previous version of the item before the version in HEAD or the
specified date, and "-rBLAH-2" would mean 2 versions of the item before BLAH
(which is different from the revision number that is 2 less than "-rBLAH").
The proposal was quite well developed - not far from being committable - but it
didn't get finished or approved or whatever. We might want to ressurect it.

I'm not sure whether that proposal would allow you to get the version that came
before a particular tag. It might, something like: "$TAGS/rel1-start/foo.c
-rHEAD-1".

Anyway, I concede that there is definitely missing functionality here, and I
don't think this has been mentioned before in this discussion so thank you for
bringing this point to light.

> (b) I could create a script to do the necessary SVN LOG scan, pluck out
> the rev#, and paste it into a DIFF/MERGE command. This could work for
> FIXED, but not PREFIXED.

Actually it does work for PREFIXED, by subtracting 1 from FIXED.

> And it depends upon well-formatted log file
> messages, and "prayer-based parsing" common to semi-formal data sets.

Yes. Similarly the script could get the information from a dedicated "bug
number" revision property (look up "revision properties" in the Subversion book
if this doesn't make sense), or from your bug tracker. Either of those could
give you the information in a more formal structure.

> (c) Use mnemonic labels for revisions, and a convention that creates a
> label named "DEFECT-FIX:nnnn" for appropriate check-ins.

Right! Now, why don't your arguments above about tags apply equally to this?
You said:

   "But creating a tag for *every* defect fix seems excessive, even if tags are
cheap. And who will remember to do this?"

I say: Creating a tag or a label for every defect only seems excessive if you
think the creation is an expensive operation or if the list of them is going to
make it hard to find other kinds of tags/labels. Creation (of a tag) is not
expensive, and to keep from cluttering your list of release tags (say), you can
use a separate tag name space - e.g. "$TAGS/bugs/..." (This begs the question
of whether the "labels" mechanism would want such a namespace mechanism.)

As for remembering to do it, well, what's there's no difference between
remembering to create a tag and remembering to create a label. Presumably you
would automate it.

> Now FIXED is
> *directly* accessible to me *and* the toolchain.

It appears to me that it would be accessible to the "svn" command via the "-r"
option argument rather than via a normal non-option argument. Is that all you
mean by "directly"?

Perhaps I'm being unreasonably hard on you. I can see that there is some
fairly profound respect in which identifying a marked point in history by path
(a tag) is different from identifying it by revision (a label) ... I just don't
know what the implications of this difference are.

> This leaves PREFIXED up
> in the air, however.

Addressed above.

> So, my ideal is the command:
>
> svn diff foo.c --revision PRIOR:!DEFECT-FIX:1234
>
> Or something like it. Here I'm using "!" to indicate a rev# expressed as
> a label (insert your own syntax here), and am assuming PRIOR means "the
> last time this item was changed" (like COMMITTED but relative to the
> other rev#).

OK. The tags version of that command would be something like:

   svn diff $TAGS/DEFECT-FIX-1234/foo.c --revision HEAD-1:HEAD

(The syntax "HEAD-1" or "PRIOR" is not supported yet, but that seems to be
equally necessary for either approach.)

> Skipping the ugly syntax and some significant issues around
> the semantics/implementation of PRIOR, I think this is a significant
> improvement over manually scanning logs.

It seems to me that the syntax and the ability to specify one revision relative
to another are perhaps some of the most important issues here. However, you
are certainly bringing out some interesting points and helping us to understand
the issue. Thanks for your continuing patience in working through this.

- Julian

>> Julian Foad wrote:
>>> Tim Hill wrote:
>>>> Yes, this is certainly one way. The main objection I have to the
>>>> current scheme is that tags are just a convention, and as a result
>>>> the toolchain cannot use the implied REV# information directly -- it
>>>> has to be manually imputed by a user and translated by him/her to a
>>>> REV# for consumption by the toolchain. This makes
>>>> scripting/automation difficult for some common SVN operations and
>>>> adds burden to the dev process.
>>>
>>> Please give an example (stating the desired task and showing actual
>>> commands for doing it) of a situation in which the user has to do
>>> this "translation".

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Thu Jun 2 15:45:44 2005

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