Tags and branches in Subversion are really just directories. The concept of what they are is not built into Subversion, but your brain.
As others have noted, tags are snapshots of your repository at a particular point in time and should not change. If you plan to change the tag, it really should be a branch.
For instance,
- I want the tag to show approved changes: make it a branch instead of the tag.
- I want to show which files were used for the latest build: Ditto.
- I want to show which code was viewed: Ditto.
But these are not branches! you whine .
Well, the proposed repository structure is this: a sentence. You can add another directory besides trunk , tags and branches for these roaming tags:
$repo/trunk $repo/branches $repo/tags $repo/moveable_tags
Now you can put the tags you change into moveable_tags and the tags that people use for releases, snapshots, etc. under the tags.
I changed the proposed repository layout earlier in one place where I worked. I wanted to remove obsolete branches and tags from the repository, but management and developers objected.
I said that deleting these files does not delete it from the repository. I could easily return them if necessary, but by deleting them I removed a lot of unnecessary clutter from these two directories. However, the developers did not feel safe. Of course, I can find them, but can they?
Instead, I added the obsolete/tags and obsolete/branches directories to the trunk , tags and branches directory level. Instead of deleting obsolete tags and branches, I just moved them. tags and branches were not cluttered, and managers and developers felt better so they knew that they needed to find these obsolete branches and tags if they were ever needed.
Say you are not doing anything with tags. You use tags as snapshots, and everything you expect to change and update is a branch. There are still moments when you need to change the tag.
And, Subversion does a better job of this than most other version control systems. This is because tags contain the entire history of their creation and changes. In most other version control systems, the history of this tag is a second-class citizen, even if it is preserved at all. You can see the tag. You can see which files and version are under this tag, but you cannot see who created this tag and how it was modified. Under Subversion, tags contain the whole story.
To make changes to the tag:
- Mark the tag.
- Make changes.
- Commit your changes.
Or, even better, use svn cp , svn mv or svn delete for the repository URL, not the working directory. For example, I created a tag for version 2.0. Suddenly, we realized that we had forgotten one very important change that was taking place in this release. Instead of checking, you do this:
$ svn cp -r 23933 -m"This change in this file should have been included in the tag" \ $repo/trunk/foo/src/foo.java $repo/tags/2.0/foo/src/foo.java
When you look at the history of this tag, you will now see.
$svn log -v $repo/tags/2.0 ------------------------------------------------------------------------ r23945 | david | 2013-04-03 11:21:55 -0400 (Wed, 3 Apr 2013) | xxx lines Changed paths: M /tags/2.0/foo/src/foo.java (from /trunk/foo/src/foo.java:23933) This change in this file should have been included in the tag ------------------------------------------------------------------------ r23932 | david | 2013-04-10 11:18:40 -0400 (Wed, 10 Apr 2013) | 1 line Changed paths: A /tags/2.0 (from /trunk:23921) Created release 2.0
I see that the tag was created a week ago from revision 23921 on the trunk. Then I see that the foo.java file was updated a week later from version 23933 on the trunk.