Search code examples
svnversion-controlconfiguration-managementstarteam

Subversion concepts for a StarTeam user


I would like to know how to do the following common StarTeam tasks in SVN

1. How to update a tag to include a newer revision of just 1 file?

After creating a View Label in StarTeam (similiar to a tag in SVN) - I was able to include a newer revision of a file into that view label - e.g. update the view to include only that file (and not others that also changed since the creation of that View Label

2. How to create a tag based on another tag?

When development continues while releasing a version, some features are not to be included although they are checked in. In StarTeam, I used to create a view label (again, like a tag) based on a previous view (and then do what I describe in question 1). I understand that in SVN I can create a tag based on another, but that it is read only, and I need a branch. but I don't really need a branch, really.

3. How to check-in / add to an existing tag?

In StarTeam the view label is on the trunk / branch, so I could check in a file after a view is created and modify the lable to include it, in SVN I have to check into the branch


Solution

  • Let me preface by saying I'm not familiar with StarTeam, so I may not fully understand the workflow you're trying to reproduce.

    Subversion itself doesn't differentiate between tags and branches. By convention, a tag is just a branch that you never modify. Even a branch is just an "svn copy" operation, there isn't a separate "branch" feature. A branch is just a cheap copy, and a tag is a branch that is read-only by convention only. Copies in svn are very cheap, so you don't need to worry about creating branches a lot - a tag is not any cheaper than a branch. You may want to read the docs on Creating a Branch. It further explains things... and has a boxed section about "Cheap Copies".

    Depending on your use of "View Labels" in StarTeam, it is possible that svn externals may be useful for your purposes. I don't generally like them, but it depends on the scenario.

    On to your questions more directly...

    1) This will depend on if there are other changes in the file. Do you want the changes from one revision in one file? Or all changes for 1 file (multiple revisions, only the 1 file). Hopefully you mean the former. In which case, the usual behavior would be to merge

    Let's say you have the following scenario:

    ------------------------------------> /trunk
     |     | fix merged to 1.0 branch
     |     v
      \------------> /branches/1.0
        |  ^ |
        |    \ /tags/1.1  1.1 tag, fix released to customer(s)
        \ /tags/1.0 - 1.0 GA tag, release sent to customer(s)
    

    You develop on trunk. At revision 10, your product is already ready to ship 1.0! You create a branch with:

    svn copy /path/to/trunk /path/to/branches/1.0
    

    You then continue developing on trunk, while also doing a bit of extra verification on the 1.0 branch. When it is ready to ship, you create a tag:

    svn copy /path/to/branches/1.0 /path/to/tags/1.0
    

    This tag is a frozen point in time that exactly matches what you are shipping to customers.

    You discover a bug/feature/update that is needed for your 1.0 release customers that has already been done on trunk. In your case, you've stated changes to a particular file.

    Let's say the changes occurred on trunk in revision 15. You'd then do (from a clean /branches/1.0 working copy):

    svn merge -c 15 /url/to/repo/path/to/trunk
    

    In the ideal case, the changes of a revision are self-contained and all files in the revision are needed. Sometimes there is also extra things you do not want to merge. In this case, after the merge, revert the changes to files you do not want merged, test everything, and then commit. There is a downside to the merge -> revert some files -> commit workflow, which is that subversion will record the merge as happening, yet you've excluded portions of it. If the branch in question isn't likely to change much further (or reintegrate to another branch) it may not matter, but I prefer creating a patch file for the changes in the 1 file you want and applying them to the branch manually for cases like that. I'm not 100% certain on the cmd line syntax, but I think it would be quite similar:

    svn diff -c 15 /path/to/file (in repo or other working copy) > my-patch.diff

    and apply with another tool. I usually create/apply patches in a GUI, so the specifics will be left as an exercise to you.

    Once done with that, you create a new tag off your branch again, that will contain your new merged change.

    svn copy /path/to/branches/1.0 /path/to/tags/1.1

    You then have a new tag that is the same as the old tag, except for having the changes to the 1 file. In #3 I will also mention that you can recreate the tag (though it depends what you are using the tag for on whether it is a good idea). r, but I would only do this if the tag does not represent shipped code.

    2) Indeed, since by convention a tag is read only, a tag from another tag would not really be different. However, if you instead use a branch for the first one, then create a tag off that (as suggested), you can later create a second tag based off of the same branch (after committing additional changes) and it will differ from your first tag by only the changes that have been applied to that branch since then.

    3) Again, you would normally use a branch. If the branch/tag is used solely internally (I do not recommend ever deleting a release tag of shipped code, although it isn't really "lost", it just shouldn't normally be necessary - ), you can just delete & recreate the tag. Consumers of your tag (working copies) can just do a normal "svn update" after the tag is deleted & recreated and will continue to work fine as if nothing happened. This couldn't be used for #1 but could be for #2 when really you just want to update a tag. The trick is combine tagging and branching to achieve what you want. If you're also using this to deploy toa website or something, you can combine branching, tagging, and externals.

    e.g. /path/to/production can be checked out which has an externals entry to /tags/1.0, and when you want to apply a fix you perform the steps in #2 and create a /tags/1.1 and adjust the externals entry. Or, just have it point at the branch and no need to recreate tags.

    I hope that is a semi-useful start.