views:

100

answers:

3

I'm so sorry for the awful question title, but I'll try to explain myself a bit more verbosely:

I'm using Git (but I guess the particular software doesn't really matter in this case) for my software project. As many projects, I'm planning on having various releases. When there's a release, I'd probably assign a commit a tag - for example "1.0". Time goes by, and code gets hacked, and eventually there's a release, with another tag - this time "2.0".

One day, I notice a serious bug, that's present in both releases 1.0 and 2.0, and it needs to be fixed. To make things difficult (and probably more realistic as well), I can't just fix it in the current master/trunk and assume everyone would be using that, because there are some backwards incompatibilities in 2.0 with 1.0 and people are lazy and don't want to upgrade.

So, what would be a good scheme to have, in order to support this kind of behavior: being able to make changes in older versions. Git seems to equate tags with releases at some level, because of the output of the git describe command ("[latest tag]-[commits since the tag]-[current commit hash]"). I probably can't avoid using tags altogether, then.

I can feel that a combination of tags and branches would be a good idea, but for some reason I can't wrap my head around the particulars with this one.

+1  A: 

You need a branch - you will do maintenance fixes and releases on a branch that starts at the release tag, while ongoing development continues on the main (master) branch.

Jonathan Leffler
If you could elaborate your answer a bit more, with an example perhaps, I'm sure people (not excluding me) would be enlightened better.
Henrik Paul
I was offline for some of the time, and Greg Hewgill has done a decent job of explaining it, so I will forego the rep points and leave it up to his answer. And point to http://www.cmcrossroads.com/ for lots more information.
Jonathan Leffler
+1  A: 

You seem to have most of the answer already when you mention branches and tags. A tag is there to mark a certain even (like a release) and branches are for parallel development. Maintenance of a certain version is generally done on a branch and you can cherrypick changesets with most of the current VCS to import a given bug fix from head/trunk into a branch and vice-versa.

You can work off head/trunk/master (whatever you "current" development branch is named) and merge bugfixes in your various maintenance branches. As soon as you have a major or minor release done, you create a branch for maintenance.

There are many ways to achieve what you want.

Keltia
+1  A: 

You definitely want to look into using a branch for this. Git support branches for this type of development very well.

By way of example, your linear version history might look like this:

---A---B---C[1.0]---D---E---F[2.0]---G---H

If you find a bug in 1.0 and want to fix it, you can't simply insert a new commit in between commits C and D. So, you might create a branch like this:

---A---B---C[1.0]---D---E---F[2.0]---G---H[2.1]
            \
             C1---C2[1.1]

Commits C1 and C2 fix the problem in that branch, where you can tag the release 1.1. Now suppose you made a change (G) in version 2.1 that you wanted to backport to version 1.1 to make the same change there. You can use git cherry-pick to do the following:

---A---B---C[1.0]---D---E---F[2.0]---G---H[2.1]
            \
             C1---C2[1.1]---G1[1.2]

Commit G1 is related to commit G except it can apply on top of version 1.1 instead of version 2.0.

In these examples, the branches (additional streams of development) are the key concept, while tags are just a convenient way to make a name to refer to the state the project was in at a particular point in time. Git supports many other ways of manipulating branches, especially with the powerful git rebase command.

Greg Hewgill