views:

275

answers:

8

My co-workers and I are having an argument over the value and usage of Tags in release/SCM systems. We're looking to the StackOverflow community to put in their thoughts to help us resolve the issue.

One side claims that Tags are a valuable addition to release management. An example of their use: we do a Maven release, which makes a new Tag (call it 1.0) which is code snapshot used for this release. This Tag should be a READONLY branch. When a bug needs to be fixed we can make a copy of the Tag into a new Branch (call it 1.1). Bug fixes go there. These fixes may be merged back into Trunk so that the main dev branch gets the bug fixes. Finally, 1.1 is released and a Tag 1.1 is automatically created. This cycle continues. The main benefit here of the Tag is that if you ever need to re-release version 1.0 for any reason, you can just release the Tag 1.0 with the confidence that it's never been altered by anyone. Also, saying "Release Tag 1.0" is cleaner than saying "Release revision 1 of branch 1.0 which is the original 1.0 without the fixes".

The other side claims that Tags aren't providing any valuable benefit, especially in a system like Subversion with global revisions, which act like a Tag in CVS. Plus, Subversion only gives a warning when committing to a Tag; it doesn't actually stop it. Their method is developing in Trunk and upon release you'd make a Branch called 1.0. You'd continue bug fixes in Trunk and if you needed to re-release those bug fixes to production, you'd merge them into 1.0 Branch and re-release 1.0. At some point, perhaps after major fixes or features in Trunk, you'd release and make Branch 1.1. Cycle continues. If you ever need to release the original 1.0 version, you'd have to check out Branch 1.0 revision 1.

Clearly both methods work. I'd like to hear the community's thoughts on which method is preferred and why.

Edit: I'm a little worried that the "best" way depends on the underlying SCM system. Either settle on Subversion for answers or if possible keep it SCM agnostic.

+2  A: 

In my opinion tags are useful. There will be times at some point in the life of the project that you come across a bug or a change and you want to know if it was there in a previous release. There will be reasons to compare code from one release to another to measure efficiencies both in performance and actually the development of the code.

Sure, there is a chance you can screw it up, but it can always be undone. There really is no reason not to, and there are several reasons why it might be useful in the future. To me its a no-brainer.

I agree that you should also be using branches and doing your development there, but anytime you actually release something, make a tag out of it.

Ryan Guill
A: 

I like to think about tags as "just a fancy name for a revision". I've always thought about them that way, and IIRC in mercurial they are just that. In subversion however, as you say, they indeed are (cheap) copies of trunk/* to tags/fancy-name/

Honestly, I'd combine the two strategies for optimal results: tag and branch upon release. Your tag is called 1.0.0, branch 1.0-MAINT. Bugfixes go into branches, and bugfix releases are tags again (1.0.1 may by a tag intended to alias 1.0-MAINT at a certain point.)

Do not forget however that tags and branches in subversion are actually the same thing: cheap copies. The only difference between them is the semantics you/your team attributes to them, so it pretty much boils down to getting people to agree on one particualr method and stick to that (might be enforced on the server, eg disallowing commits in tags/ except for release coordinators etc.)

The problem I see though with the second approach is: how are you going to make an easy distinction between software in the field if you re-release 1.0? That means that you may have a 1.0 and another 1.0 actually referring to a different code base... .

Vincent De Baere
+2  A: 

From an SCM agnostic point of view, a tag is very different from a revision.

Both may be implemented in the same way, both represents a "time line", but their goal is different:

  • a tag represent an immutable state where all files are referenced by a unique id. It is a name representing many things but mainly a stable state, ...)
  • a revision represent a commit transaction (not all SCM have those, especially the old ones with a 'file-by-file approach'). All commits do not represent a "stable" state (as in "compile" or "execute" successfully). They are just a new element of the global history.

The problem with SVN is that revision, tag and branches are all implemented the same.
But I would still prefer the option where a tag is used as a "read-only" branch.

VonC
+1  A: 

Yes, you want to use tags.

Think of a tag as just a label or a name for a particular revision. It is very helpful in my experience to tag important milestones in a project, whether it's for production release or even for interim QA releases. You often will want to go back in time and see the source code for a particular release.

If you branch upon release, you can always figure out which revision was released to production, but this is kind of a pain compared to just looking at a tag. If you don't use release branches then it will be easy to lose track of which revision was used to create a particular build.

The problem with svn is that it blurs the distinction between tags and branches. Anyone can always commit to a tag, so it's not guaranteed to be fixed/immutable. In other VCS like PVCS, a "tag" is unchangeable. You can adopt a team convention to prevent commits to tags, or even maybe use commit hooks to prevent commits to tags.

Ken Liu
A: 

Immutable snapshots of a project's source code (and executable) are invaluable for doing testing of any kind, whether structured testing or field usage. For structured testing, you're going to be creating data that might be referenced months or years in the future. Anytime you revisit that data, Murphy's law says you'll need to know what code it comes from and unless you went to the trouble of citing a particular snapshot of the source code, it will be impossible to tell with confidence what source code corresponded to that test data.

I can't tell you how many times someone's come to me and said "This microcontroller code's not working, can you help?" and I ask them, "What version are you using?" and they say "I'm not sure" because they're not doing good release management (at the very least putting a sticker on the device, better to put versioning info in EEPROM that can be queried in realtime). >:(

Jason S
A: 

In SVN, the technical difference between using a tag and tracking a revision is nil. I find myself minimizing tag use based on how SVN's implementation is simply a cheap copy and clutters up your "structure space".

The real difference comes when communicating a particular baseline to a large team of developers. Revision tracking brings an extra layer of abstraction that can become a source of errors. And as we're all aware, when you're dealing with 50+ developers, any source of error will become an area of confusion and wasted time. A verbose tag can eliminate that confusion and remove any doubt as to what a baseline's purpose is.

Dan
A: 

I'd combine both approaches. Whenever you make a release, tag it. Tags should never change, so the presence of a "1.0.0" tag is an indicator that you shouldn't be trying to release anything else as 1.0.0.

At the same time, when it came time to do 1.0.0, I'd put it onto a 1.0 branch. So the flow is: branch trunk to 1.0, tag this new 1.0 as 1.0.0, and deploy. Then bug fixes can be done on the 1.0 branch (to avoid getting mixed up with any 1.1-targetted development that may already be on trunk now) and merged into trunk. Each release of the fixed 1.0 is tagged as 1.0.x from the 1.0 branch. This is basically the approach we use at work with Perforce, and that's very similar indeed to Subversion. (Reading through the replies, I think it's virtually identical to Vincent's recommendation)

As far as the comment about tags being redundant because you have revision numbers--- that's largely true, except that tags also specify a scope: i.e. which files in the repository are covered by the tag. You can reasonably ask someone to look at /svn/proj1/tag/1.0.0 and they are immediately looking at a coherent workspace. If you ask them to look at revision X, they have to first look at revision X to see that it was changing (say) /svn/proj1/trunk/Makefile and hence deduce that /svn/proj1/trunk/@X is what they should be looking at. What happens if revision X touched files in proj1 and proj2? Which is of course evil, but strictly speaking you should be saying /svn/proj1/trunk/@X. And where is the list of revision numbers stored? How do we know that 1.0.0 is revision X? It should IMHO be possible to determine that just from the repository.

In systems like Git, tags and branches are still basically the same thing (just references to the object database), but the convention is that tag refs don't change, and branch refs do (and preferably with a specific constraint on how they change). Perforce also has "labels" which are ways of grouping a set of file revisions together independently of a changelist; which is essentially a tag, but more confusing: historically we've used changelist numbers (equivalent to Subversion revision numbers) qualified with the name of the branch they should be on to identify versions. The two are almost identical any way, so here I guess TMTOWTDI.

araqnid
+1  A: 

We use tags (labels) when creating new baselines. We do it once a week, but some teams do it even several times a day.

The point (for us) is always making sure the new baseline is stable: so it's not just a build, is a build that passes the entire testsuite, several hours of automated tests plus potentially manual exploratory ones too.

Then the baseline is used as starting point for all tasks during the next iteration: every new task is a new branch starting from the baseline, which is known to be stable so whatever is broken in the task should be easy to trace inside the task itself.

Normally we only put tags (labels) on the main branch (or trunk or master depending on your SCM flavour) which is the integration point for all the other branches.

When we release an official product we create a "release branch for it" so it will only receive fixes while new development stays on "main". Then these "maintenance branches" (hopefully only one or two at a time) can be tagged too.

pablo