On Sun, Jul 21, 2013 at 2:26 PM, Omer Katz <
omer...@gmail.com> wrote:
> Can you explain again what's wrong with git-flow more elaborately?
> What should be our workflow then?
The problem is that git-flow uses master as a deployment branch.
You create your release branch from develop, get it polished and
ready, and then merge it to master, tag it, and release it. The
master branch then becomes the very serial location from which to
deliver your actual release, and that's the crux of the problem.
Let's say you have this:
develop: ---*---*-------*
\ /
release-1.1.0: *---*---*
\
master: -*-------------*----
1.0.0 1.1.0
So, master is at version 1.1.0. Then you discover an issue that's
going to require you to make a couple of patch releases: 1.0.1 and
1.1.1. 1.1.1 would go well, since it's next in line from 1.1.0:
develop: ---*---*-------*-------*--
\ / /
release-1.1.0: *---*---* /
\ /
hotfix: \ *
\ / \
master: -*---------------*---*---
1.0.0 1.1.0 1.1.1
So now the current state is 1.1.1. But what about 1.0.1? You
wouldn't want to actually merge 1.0.1 to trunk and tag it. That
would mean master would be some combination of the content from
1.1.1 and the fix made for 1.0.1.
In other words, this would be bad:
develop: ---*---*-------*-------*--
\ / /
release-1.1.0: *---*---* /
\ /
hotfix: \ *
1.0.0 \ / \ 1.0.1
master: -*---------------*---*-------*
\ 1.1.0 1.1.1 /
hotfix: '-----------------------*
You really want this:
develop: ---*---*-------*-------*--
\ / /
release-1.1.0: *---*---* /
\ /
hotfix: \ *
1.0.0 \ / \
master: -*---------------*---*---
\ 1.1.0 1.1.1
hotfix: *
1.0.1
But that's not the git-flow model.
The other way to approach this is to treat master as your main
development branch and use release branches to do the actual
release. In this model, it would look like this (not lines composed
of dots are cherry-picks, not merges):
master: -*---*---*---*---*---*---*
\ . \ .
\ . \ .
release-1.1.x: \ . '-------*
\ . 1.1.0
\ .
release-1.0.x: '-------*
1.0.0
Then a patch release would look something like this:
fix for backport
|
v
master: -*---*---*---*---*---*---*---*---*....
\ . \ . . .
\ . \ . . .
release-1.1.x: \ . '-------*-------* .
\ . 1.1.0 1.1.1 .
\ . .
release-1.0.x: '-------*---------------------------*
1.0.0 1.0.1
You can still use feature branches for development (and I encourage
it!), and I'd add one caveat there: make sure when the feature
branch is merged that it's not a fast-forward merge (git merge
--no-ff). This makes it easier to revert a feature from the master,
in the event something doesn't work out well. This sort of strategy
allows some of the flexibility of git-flow:
* Use of feature branches.
* Have a release branch to stablize for the release, and leaves
master open for more development.
What you lose is the abliity to have master be something that you're
ready to push into production. I think it's a fine tradeoff though.
The only modification to this I would consider is that the first
major/minor release come off of master instead. You'd prevent new
stuff from landing for a bit, but I don't expect that Nose2 will
need much time to vet stability. FWIW, this model is pretty close
to what happens for Linux kernel development and is pretty close to
what I've had my employees at my workplace do for years now.
One thing about this model is that you *never* want to merge the
release branch back into master. If you do, then you can run into
some interesting problems. I've answered one such problem on
stackoverflow:
<
http://stackoverflow.com/questions/15807522/why-is-git-log-cherry-pick-not-removing-equivalent-commits/>
I hope all of this makes sense. I apologize for my crude ASCII art
graphics... email is not a terribly good medium for this kind of
graphical explanation.
-John