I’ve used git flow for most of my software projects — specifically for those
that have versioned releases. The original
post describing git
flow is still the best overview of how it works. In short, you have a master
branch where every commit is a merge commit. Each of these merge commits
represents a new release, and is tagged with the version number of that release.
The merge brings in all of the subsidiary commits and feature branches that make
up that release. Ongoing work happens on a separate develop branch. This is
where you merge in completed new features and bug fixes on a day-to-day basis.
develop should always be a stable version of the software — you don’t merge a
feature branch into develop until it passes all of your tests and is
“complete” with regards to the feature you’re trying to implement.
My favorite part of this model is how each release is just some tagged commit on
the master branch. You want to see the code for the latest released version?
That’s easy — git checkout master. You want version 1.2.5 specifically? Use
git checkout 1.2.5 instead.
Unfortunately, the git flow tool has
implemented a slightly different
behavior for awhile now. That
patch makes git flow tag the last commit on the release branch, instead of the
merge commit on the master branch. The reasons for this might be perfectly
valid, but it’s not what I want, and it’s not what the original git flow post
described. That means that I can’t use git flow release finish as-is.
To recap the usual process:
$ git flow release start ${VERSION}
[ bump version numbers and release dates if needed ]
$ git flow release finish -s -m ${PROJECT}-${VERSION} ${VERSION}
The first command creates a new release branch called release/${VERSION}. If
you need to make any changes that bump version numbers or release dates in the
actual files in your repository, you do that on this new release branch. You
then finalize the release, which merges the release branch (along with any new
commits on develop) into the master branch. It also creates a tag named
${VERSION}, and because of the -s option, signs it with my GPG key.
The problem is that this tag is placed on the wrong commit. That’s easy to fix, though:
$ git tag -sf -m ${PROJECT}-${VERSION} ${VERSION} master
I also like to create a -dev version tag on the latest develop branch, so
that git describe always gives me a nice looking version number, regardless of
which branch I’m on:
$ git tag -s -m ${PROJECT}-${VERSION}-dev ${VERSION}-dev develop
And that’s it!