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

Re: Updating a live website with a post-commit hook script

From: Bob Proulx <bob_at_proulx.com>
Date: 2006-07-01 03:52:56 CEST

Les Mikesell wrote:
> Bob Proulx wrote:
> > Tags in CVS are often used like cheap branches. What you describe
> > looks like a subversion branch.
> Yes - I want a branch that represents exactly the testing workspace
> but I only want it to appear to anyone else when testing is complete.

Changes in the subversion repository are atomic. But updates to a
working copy are not and will take time to checkout. Is atomicity
during a checkout important? If so then you would need to check out
on the side and do a rename probably through a symlink to quickly cut
over to the new copy. But achieving perfect atomicity can be
difficult. In fact I don't know how to do it.

> > However in CVS tags can be moved.
> The point of the tags is that someone has blessed this particular
> group of versioned files, which in CVS are versioned individually.

I think the key point is that in cvs you can move a tag creating a
"floating tag" behavior. In svn this is not supported. But
fortunately other ways are provided to handle this.

> > This means that the CVS operation of moving tags does not map directly
> > to a subversion operation.
> Tags don't actually have any effect on the file versioning and moving
> them doesn't affect any history. It only affects which file versions
> are identified by that tag.

Negative. We are talking past each other. Because tags in cvs do
affect file versioning and moving them definitely changes history.

> > > That sounds reasonable. Is there a way to rename existing tags? In
> > > the CVS scheme I would use rtag to change the RELEASE tag to
> > > RELEASE-1, etc. for a few downrev versions, then add a new RELEASE.

If yesterday I cvs checkout -rRELEASE I get a set of files identified
by the RELEASE tag. Then you bless the RELEASE tag either on new
files or on later versions of files to identify a new contour with
RELEASE, moving that floating tag to a new set of files. Then
tomorrow I cvs checkout -rRELEASE and I will get a different set of
files than I got yesterday.

The tag RELEASE now identifies something different then it did before.
Files identified by RELEASE have changed. And cvs does not record the
history of the movement of tags and so looking at cvs log will not
show me when the RELEASE tag was applied nor when it was moved to a
new version. The two trees both checked out with RELEASE are
different and I have no way to tell when this occurred nor even
exactly what changes occurred.

Using a floating tag like that is common in cvs. This is why I call
it a "cheap branch". It is maintaining a branch-like behavior that
file versions can change from moment to moment with different file
revisions being identified by it. By my reasoning if you can get a
different result at different times from the same command then it has
branch-like behavior.

> I think this is leading to using 2 branches - one for the test snapshot,
> then one for the release after someone blesses it.

That seems perfectly workable. I think it requires more merging
because you will need to merge changes from the trunk onto each
branch. But that should still work fine.

> > This is just semantics but it sounds more like a branch than a tag to
> > me. Branches can change and mutate over time. But tags imply
> > something that does not change. In CVS it was just a quirk of the
> > implementation that that tags were also used as cheap branches.
> I think of it a different way. In CVS, files are versioned separately
> and tags are the way you identify a set of file versions so you
> can operate on the same set repeatably.

Agreed to this point.

> The files are expected to continue to change and the point of the
> tag is to identify the state of a snapshot of the set.

This is where we diverge. In CVS a tag can move. Or you can choose
never to move it.

A tag such as RELEASE-4.2.1 I would expect never to move from the
files it identifies. But a tag such as LATEST I would expect to float
to the top and always track the HEAD. They are both tags. But the
purpose they are being put to is completely different purposes.

> Normally you would just keep adding new tags with increasing version
> numbers

For RELEASE-4.2.1 I would expect that to never move and never be
deleted. I would expect it to be followed by RELEASE-4.2.2,
RELEASE-4.2.3, RELEASE-4.3.1, etc.

>- and you can do that too if you want but then everyone has to track
>what is the latest tagged version. For this purpose I just want to
>identify the latest file versions that have been tested together for
>current production and the one to use to back it out and floating a
>known tag seems easier than tracking variable ones.

That is the *other* behavior of cvs tags. LATEST would move. But
when LATEST moves the history of where it pointed to previously is
lost. This is not supported by cvs. But svn uses directory trees for
tags and versions tree operations.

> > I think because subversion versions directory trees that you can
> > automate making perfect merges to branches behind the scenes. People
> > would never have to deal with it but a script could easily do so. Of
> > course you have to get it going but then...
> >
> > THEN=$(date +%F-%T)
> > svn copy $URL/trunk $URL/tags/release-$THEN
> > ...work.test.work...
> > ...test.work.test...GOOD.VERSION!...
> The catch is that the top line needs to overlap the bottom
> part independently. That is, the tester takes the current
> repository head as his starting point.

I think I covered that. However I did create a very fast and loose
example and admit there are many details "left as an exercise for the
reader". :-)

> Meanwhile developers may commit changes that go into the next cycle.


> If the tester finds a problem with one file, with CVS he could fix
> it and commit that file or ask the developer to do it, then update
> that file into his workspace before the rtag operation.

There are different ways to do that change. On a branch? On the main
trunk and then merge back into the branch? On the main trunk and then
just move the tag to the file on the main trunk? In that last case
what if the main trunk has other incompatible changes already?

Could you outline that part in a little more detail?

> If you can't do individual file changes in subversion,

I don't quite agree with that statement.

> I think that means the testing copy has to be on a branch so as not
> to interfere with other concurrent commits on the main trunk that we
> don't want to pick up yet.

That would work just fine.

> But we probably do want the fix the tester adds put
> into the trunk. Does that become a separate operation
> or is there a way to finalize this such that the testing
> workspace can be blessed into a release tag or branch and
> any changes also go back into the trunk where other changes
> may have occurred by now?

Have you seen this best practices reference? I think it is really
pertinent to your problem at hand.


Look specifically at the "Know when to create branches" section.

> > NOW=$(date +%F-%T)
> > svn copy -rGOODVERSION $URL/trunk $URL/tags/release-$NOW
> > svn checkout $URL/branch/latest .
> I don't want anything else that has been committed to the trunk
> at this point other than what the tester might have changed or
> requested to have changed. Isn't this operation going to pick
> up unrelated new work?

No. Because I specified the -rGOODVERSION it will select specifically
that revision of the trunk. Developers may have committed changes on
top of that version but this will copy it based on the specified
version. New commits will not be copied to the tag.

The hard part of doing it this way is identifying the GOODVERSION
number. That will be something like 42123 or some such number.
People don't work well with those types of numbers. But scripts and
programs can handle it fine to create tags based upon that number and
humans deal with named tags well enough.

> > svn merge $URL/tags/release-$THEN $URL/tags/release-$NOW .
> > svn commit -m "$NOW -- Release latest..."
> > ...work.test.work...
> > ...test.work.test...GOOD.VERSION!...
> > NOW=$(date +%F-%T)
> > svn copy -rGOODVERSION $URL/trunk $URL/tags/release-$NOW
> > svn checkout $URL/branch/latest .
> > svn merge $URL/tags/release-$THEN $URL/tags/release-$NOW .
> > svn commit -m "$NOW -- Release latest..."
> I'm not sure I understand all that but I don't think it is going
> to get the fixes back into the trunk as well as identifying the
> branch/tag exactly as tested.

The process model I was proposing was an unstable trunk where all
development happens on the main trunk. Then a stable branch where
known good snapshots of the trunk are captured with a tag.

A disadvantage is that the main trunk must periodically work and
become a good version so that it can be captured. Or it is an
advantage. This is where different people will have different

I consider it an advantage. One of the premises of agile code
development is that the project should be always kept in a releasable
state. Therefore I consider this normal when working in an agile
development environment. If the code is always releasable and always
passing all tests then it is easy to periodically make a release from
the main trunk. Or as in the case above pull changes from the main
trunk into the release branch.


To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Sat Jul 1 03:54:03 2006

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.