How to move a Tag in SVN

12,451

Solution 1

Tags and branches do not differ in SVN. All the difference is in policies that teams follow for how to work with tags and branches.

So you can merge changes into a tag and commit a new revision the same way you would do it with a branch. It's understandable that usually you don't want to do that, in order to "tag" the exact versions of files that you used for a release. But if it is really required, you can make an exception from this rule once.

Alternatively, you can remove the tag, and then re-create it using the right revision(s).

A couple of links to the SVN book: "Tags", "Branch Maintenance"


ADDED: So, it sounds that such re-tagging is not a rare, untypical use case but rather a regular practice in your team. Seems with tags you do not just give a name to a particular snapshot of your files, but want that name to follow subsequent updates of the files, forgetting its previous place. Also it seems you find branches inconvenient for your workflow.

Well, I do not think there is a simple and clean way to achieve what you want with SVN. In my opinion, it's better to "embrace" branches and learn how to use them efficiently.

Solution 2

Tags and branches in Subversion are really just directories. The concept of what they are isn't embedded in Subversion, but your brain.

As others have stated, tags are snapshots of your repository at a certain point in time, and should not be changing. If you plan on changing a tag, it really should be a branch.

For example,

  • I want a tag showing the approved changes: Make it a branch instead of a tag.
  • I want to show what files have been used for the last build: Ditto.
  • I want to show what code has been reviewed: Ditto.

But these aren't branches! you whine claim.

Very well, the suggested structure of a repository is just that: A suggestion. You could add another directory besides trunk, tags, and branches for these moveable tags:

$repo/trunk
$repo/branches
$repo/tags
$repo/moveable_tags

Now, you can put the tags you change under moveable_tags, and the tags that people use for releases, snapshots, etc. under tags.

I've modified the suggested repository layout before at one location where I worked. I wanted to delete obsolete branches and tags from the repository, but management and the developers objected.

I said that deleting these weren't deleting it from the repository. I could easily get them back if needed, but by removing them, I eliminate a lot of unnecessary clutter from these two directories. However, the developers didn't feel secure in this. Sure, I can find them, but can they?

Instead, I added an obsolete/tags and an 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 weren't cluttered, and the managers and developers felt better that they knew were to find these obsolete branches and tags if they ever needed them.


Let's say that you're not doing anything fancy with tags. You use tags as snapshots and anything you expect to be changed and updated is a branch. There are still times when a tag might need to be changed.

And, Subversion is better at handling this than most other version control systems. That's because tags contain the entire history of their creation and changes. In most other version control systems, the history of that tag is a second class citizen if it is even kept at all. You can see the tag. You can see what files and version are under that tag, but you can't see who created that tag and how it had been changed. Under Subversion, tags contain their entire history.

To make a change in a tag:

  • Check out the tag.
  • Make the change.
  • Commit your change.

Or, even better, use svn cp, svn mv, or svn delete against the repository URL and not against a working directory. For example, I created a tag for release 2.0. Suddenly, we realized we forgot one very important change that's going out in this release. Instead of a checkout, 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 trunk. Then I see that the file foo.java was updated a week later from revision 23933 on trunk.

Solution 3

I have found 1 easy way to do this (I.e. move a tag for a file) using tortoise SVN.

  1. browse your repo by right clicking on your checked out project dir and selecting "Tortoise SVN->Repo-browser"
  2. Navigate to the file you want to change within your tags/ directory
  3. right click on the file and select "checkout".
  4. Select a temporary directory on your HD and hit ok.
  5. Overwrite this file with your updated version (using your local file exporer, not the SVN repo browser)
  6. right click on the file and select "SVN checkin".

Job Done.

To do the same thing using CVS is trivial, just go to the required directory and type: "cvs tag -F tagname filename" SVN doesnt really have tags, which makes it painful to use (In my opinion).

Not sure why this has been down voted - it is how we solve the exact problem set in the question.

Solution 4

Your comment on @Alexey Kukanov's answer indicates to me that what you really want is a branch, not a tag. A tag is historical record of a single, unchanging point in time. A branch is a copy of the code that will undergo further changes as time goes on. You're talking about the latter. It's standard practice to create "bugfix" or "production" branches for each release that you're supporting, and either commit changes directly on the branch[1] or merge them from the trunk.

Tags, in this case, would be used to create "copies" of the branch to indicate "exactly this code was in production at this particular time". So you can easily go back and compare against it if the need arises.

[1] ... and later merge them to the trunk as appropriate

Share:
12,451
YoYo
Author by

YoYo

Retooling myself constantly.

Updated on August 07, 2022

Comments

  • YoYo
    YoYo over 1 year

    This question can be rephrased as:

    How can I include a single change in the trunk of a specific file into an existing TAG.

    A simple question, but one I was not able to resolve to satisfaction myself.

    The concept comes from other SCM tools, where you just move a tag over the different revisions and "stick it" to the exact revision you need. Those other tools have the native understanding of what a Tag is, where SVN generalized everything as a copy-branch.

    Below answers I have seen on other bulletin boards and posts on this same, and as such were already considered and rejected:

    1. This is not the proper use of SVN
      • Actually, SVN was designed to be generic, and accomplish many use patterns
      • This is a mission to find an answer. I understand the challenges, and the possibility of never finding an answer. Maybe I will switch to a different tool.
    2. Why are you using SVN such our so, it is better to do this and that.
      • There are many use patterns or SCM models that can be adopted. In my case specifically:
        • The Trunk represents ongoing development, and small patches are applied to it.
        • Production is a single TAG
        • the turn-around from development is very short and aggressive, and as such we cannot work with several complete production releases. That means I can not every-time create a new tag for every little sub-change deployed in production.
        • So in short "Complete Packaged Production releases do not exist in my scenario".
      • This is my Use case scenario I need.

    Well, I wont be presumptuous, and I will read every single solution provided and reconsider as needed.

    • Groo
      Groo almost 13 years
      If I got it right, you want to merge changes done to a single trunk file, into a branch path? In what way do you want this to differ from standard merging in SVN?
    • Tyler
      Tyler almost 13 years
      So you only have one tag at any given time? There's no technical reason this won't work, but it's not exactly how tags usually work. Every time you release a version, you might want to tag it with the version number (like 1.0) and then if you need to release a slightly changed version, make a new tag called 1.0.1. Then you could have another tag called "latest" or something which always has your latest release.
    • John Little
      John Little about 11 years
      I have the same problem. How do you "move" a tag, i.e. if you have already tagged your head by copying it to say tags/1.5.0, then you realized you need to update one file, and include it with this tagged version which will become the release. You cant create a new tag, as it has to be "1.5.0" for example. We need to tag the new version of the one file, kind of overwerite the old version. This does not seem to be possible in SVN. if you try to copy the new version to the same tag, it complains that it already exists. We cant "checkout" the tag into a new directory, as repo is too big.
  • YoYo
    YoYo almost 13 years
    Yes, all that I considered: merging into the tag, or recreating the tag. Problem is, it is to complex for the amount of people putting a single file into production. I really need to have a simple action that allows me to single out a file, and just merge that into the production tag.
  • Tyler
    Tyler almost 13 years
    I think you can just svn switch to the tag, get the file (from trunk or wherever) and put it in your working copy, and then svn commit the change. Then svn switch back to trunk, to make sure you don't accidentally commit new development which belongs on trunk, to the tag.
  • usethe4ce
    usethe4ce over 10 years
    This is exactly the missing step I was looking for. You want to simply do a merge, but in order to do so you must first check out to some other location. And BTW, if the change is one you've already checked in after the tag, you can just do a proper merge in step 5.
  • robert
    robert over 4 years
    I think this answer might be the closest to what's being asked, while also using idiomatic SVN operations