46

Our software product line requires developing and maintaining multiple software versions concurrently. We are relative Git newbies and recently adopted Git Flow to take advantage of Driessen's branching model. We have a very small software team with few dedicated developers (we all wear many hats) and no "integration guru."

Much searching has turned up little specific advice on how to adapt Git and Git Flow to our needs. What has turned up is that Git Flow is not well suited to supporting multiple versions concurrently. One related discussion on SO has answers indicating separate branch names need to be used to track separate versions' histories. This, and related strategies, eliminates Git Flow unless it is modified; see our team limitations above for a reason why this isn't practical for us.

The key question is what have others found to be a good approach for implementing Driessen's branching model as closely as possible while supporting multiple release lines?

UPDATES:

Distilling the answers below (particularly @Rasmus') with more targeted searching and internal discussions on a few options leads to the following solution that we are implementing, and which I offer as one approach that may be relevant to similar teams under similar conditions.

We won't continue to use Git Flow. Instead, we will apply Driessen's model to each individual release line in a repo by prefacing each branch name with its intended release string, e.g.:

r1.5/develop

All versions of a project are contained in the Git repository. Starting a new project version consists of creating a small set of new long-lived branches prefaced by the release string (e.g. r1.6/develop and, in our case, r1.6/release; no master with its implication of the single current good buildable state).

We establish one central public repository per project on a server that will be the main avenue for sharing code through local repo remote links. A push to this repository signifies code that is ready to be consumed by others. Merging RX.Y/develop into and then pushing the RX.Y/release branch signifies code that is intended for release. feature, hotfix, et. al. branches are handled similarly. The branch merge/commit history for a given release line is clean and understandable. We don't want the typical Git distributed repo strategy in favor of avoiding the complexity of merging such repos that, over time, are likely to diverge in structure.

In some Git GUIs (such as SourceTree for example) this branch structure is recognized and displayed as hierarchical, which helps understand the top-level history of a project from the branch structure.

Apologies for not up-voting any answers; my reputation on SO is not yet the minimum required to do so.

Community
  • 1
  • 1
mklein9
  • 572
  • 1
  • 5
  • 9
  • This question appears to be off-topic because it is about best practices for software development and revision control, not about programming as such. – Hans Then Aug 13 '13 at 23:22
  • 22
    @HansThen: I disagree. Software best practices just like software design patterns are programming topics. I searched for this topic and found it in stackoverflow, just where I expected it. – Bernard Oct 23 '13 at 08:01

3 Answers3

9

we are having a similar setup except we have more than 300 dedicated developers, we have exactly what you described several revision we need to deliver to different customers.

We have divided it so we have an initial ref like refs/heads/platformX.Y/ then we build on that

So depending on what you need to do you checkout platformX.Y/develop and start working from that point on a feature branch and you merge back to develop when you are done.

This works for us and we can follow the nvie model.

on top of everything we are merging all these platformX.Y branch to our main develop branch so errors corrected on those branches are released in to the latest software as well.

  • Thanks @Rasmus. Based on your answer, my thinking is evolving toward defining two long-lived branches, develop and release, per "release branch group" (for lack of a better name), e.g. r1.2/develop and r1.2/release. Does merging all the platformX.Y branches into the main develop branch cause difficulty in understanding branch histories, especially for non-gurus? If multiple releases are actively worked on for extended periods of time, how can one comprehend the state of the top-level develop branch? – mklein9 Aug 15 '13 at 18:45
  • Well it all depends on the situation, we have areas where we don't merge, so we merge to the main "trunk" and do a git checkout of the subdirectories that should not be merged to the develop branch. But it is branch by branch we have that situation. – Rasmus Østergaard Kjær Voss Aug 15 '13 at 19:29
  • What I don't understand in Rasmus git work flow model is what happens with features/bugs merged into refs/heads/platformX.Y/ that do not exist into develop? (I know it is an old discussion, but we have a problem similar to OP and am trying to find best solution). – viktor Feb 24 '15 at 12:51
2

Our usual development process fits Driessen's flow workflow well, but we sometimes need to develop a branch with several features for a specialized release, where we don't want the bulk of ongoing development included. We've found a way to do this within flow using existing tools, with just a couple of extra steps. (We are working in mercurial, but the options to git flow and hg flow are the same.)

For example, our next normal release is 23.0, and our special, "sandboxed" release is 22.4.2. For these cases, we:

  1. Early on, before the new features are created, create a release branch 22.4.2 for the special release off of develop. It's fine if some features were started earlier as long as they don't come after any work on develop that we want to exclude.
  2. Make a tag there for convenience (start-22.4.2)
  3. Start each new 22.4.2 feature with start-22.4.2 (a changeset on develop) as it's parent/base. This prevents any work merged to develop in the meantime from leaking onto the release branch. Both the commandline and Sourcetree support choosing a parent besides the tip for git flow feature start.
  4. Merge manually from the tip of the 22.4.2 branch to the feature, if desired, and as often as desired, to bring in any completed features from the branch. This lets us deal with any interactions of concern among the new 22.4.2 features on the branch.
  5. git flow feature finish the feature, which merges it to develop as normal. (For us, these features are meant to be included in future releases. We're only protecting 22.4.2 from less-tested work.)
  6. After finish, we manually merge the last changeset before the close of the feature onto the 22.4.2 branch.
Joshua Goldberg
  • 5,059
  • 2
  • 34
  • 39
  • I noticed a mistake in the above: You must start flow from the *parent changeset* of the new branch, because the starting changeset is required to be on develop. (You can't start from the changeset that actually created the branch.) – Joshua Goldberg Apr 14 '15 at 17:10
  • To start at step 3, without the tag: 1. sanity check: `hg log -r 'branch(default) and parents(first(branch(beta24.0)))'` should give exactly one result. 2. `hg flow feature start -r 38f21bfeef47` (You cannot specify the revision programmatically for some reason.) 3. sanity check #2: `hg log -r 'children(parents(.))'` should include the start of the branch you meant to precede. – Joshua Goldberg Feb 04 '16 at 16:25
  • Helpful to also `hg commit --amend -e` to add "from the parent of beta24.0" to the commit message of the feature start. – Joshua Goldberg Feb 04 '16 at 16:37
1

One solution is to change the config variable gitflow.branch.develop. You create a branche at your released version and use that branch as your new develop branch. From there, you use the usual git-flow commands. If you want to automatically merge that work back into the original develop branch, change the gitflow.branch.develop variable before the git-flow finish command.

Nowhere man
  • 5,007
  • 3
  • 28
  • 44