87

We are trying to adopt the successful Git branching model implemented by git-flow. Now, we are working on at least two release-branches, one for the latest stable release and one for the next ("preview") release. What I don't understand is why all releases seems to "linearized" to the master and tagged there. Why not tag the releases in their release branches? Why the master at all? Or why a develop branch and not use master for it?

Mot
  • 24,166
  • 22
  • 78
  • 117

6 Answers6

77

In the git-flow model, your "latest released" version actually maps to the master, while your "preview release" maps to a git-flow release branch. It is forked from develop and finally merged into master when the actual release happens. Then this will become your "latest release" and you will usually fix only bugs for that release, using git-flow hotfixbranches. In this way, your master always represents the most stable state of your latest released version.

If you want to fix bugs for older releases or do any other develop there, you will fork a support branch from the appropriate commit in master (you will have all versions ever created there). support branches are still experimental (according to the docs) and are not well documented. But as you can see from the command line help:

usage: git flow support [list] [-v]
       git flow support start [-F] <version> <base>

these branches are just started and not intended to be merged back to master nor develop. This is usually fine, as fixes to "ancient" releases or features requested by customers to be implemented in "ancient" releases can't or should not go back into master. If you still think, you want to port a fix to your main development line (represented by master and develop), just start a hotfix, cherry-pick your changes and finish the hotfix.

danio
  • 7,981
  • 5
  • 42
  • 54
mstrap
  • 15,236
  • 6
  • 50
  • 77
  • 18
    This doesn't deal with a slow pipeline from Test to QA to production. There may be two (or even more, but let's just say two for now) release branches open, each in a different stage of that pipeline and each needed to allow fixes for bugs found in test. The _develop_ branch would then be where features were being accumulated for a release whose branch has not yet been made. In such a situation, a fix on release n-2 would eventually be merged to develop, but would skip release n-1, at least following the standard git flow. This would lead to a regression on n-1, fixed eventually on release n – Brendan Apr 13 '15 at 12:51
  • Why wouldn't release branches be kept and once newer release branch is created, older evolve into a "support" branch? – lkanab Oct 21 '17 at 07:34
  • 1
    Why release branches are "forked" from develop and not just "branched off" from develop? – Sandra K Jul 19 '18 at 19:48
  • [gitflow-avh](https://github.com/petervanderdoes/gitflow-avh) looks like a maintained (i. e. not dead) fork of the original gitflow. `git flow support` is not marked experimental. – Timo Verhoeven Aug 27 '18 at 14:52
9

Looks like mostly a mental model with a bit too much emphasis on branches. I agree, you could just tag the commits you release instead of merging them back into master.

The picture is pretty, though. Merging everything back into master gives a clear indication of the releases in temporal order instead of having version tags strewn all over the graph.

I think this model does not work for bugfixing in older releases, though. It messes up the neat ordering.

  1. Say we have released Version 1.0.1 and later added features and released 1.1.0.
  2. We discover a bug in 1.0.1 and want to fix it in both version
  3. We have to add 1.0.2 after 1.1.0 in master and then directly atfer (or before) also 1.1.1.

To answer your question: I think this is a set of rules that makes for a simple mental model in some cases. Not all of the rules make sense from a purely technical point of view but that doesn't make them bad. Mental models be good for 'em humanses.

Sarien
  • 5,956
  • 5
  • 32
  • 46
  • 1
    `support` branches are designed for bug-fixing in older releases, though still labeled as 'experimental'. – mstrap May 31 '13 at 21:21
2

I personally think the mentioned git-flow is overcomplicated.

If you are using GitHub try the GitHub flow (as described by Scott Chacon).

It is especially useful for collaboration on multiple features, code-review and you could combine it with your Continuous Integration solution using the Commit Status API.

UPDATE: There is a new official website of The GitHub Flow™

UPDATE 2: There is a new official (and simplified) GitHub Guide for The GitHub Flow™: https://guides.github.com/introduction/flow/

Haralan Dobrev
  • 7,233
  • 1
  • 44
  • 62
  • 10
    The GitHub flow is only suitable for a non release-centric context : _The git-flow process is designed largely around the "release". We don't really have "releases" because we deploy to production every day - often several times a day._ – Remi Mélisson Jul 15 '14 at 08:43
  • 10
    I would also add that git-flow doesn't really work that great *in* a release-centric context that has maintenance releases. E.g., what happens when a 1.2.1 release happens after a 1.3.0 release? It presumably can't be merged to `master`, an anomaly of the chronology of the work. – Ken Williams May 01 '15 at 19:44
  • @KenWilliams as described in [mstrap's answer](https://stackoverflow.com/a/16866118/3429133), this is what `support` branches are for. But you are right, it is indeed an anomaly that such releases aren't merged back into `master`, which—to my understanding—should hold all production releases. – beatngu13 Aug 21 '20 at 09:56
2

In my case, I have two version of the same software that the basics are the same but each version has some different features.

So I create two worktree that means, create two relevant long-running branches beside the master.

$git worktree add -b version-silver ..\version-silver master
$git worktree add -b version-gold ..\version-gold master

Then I have:

$git branch
master  # base stuff here
version-silver # some normal features
version-gold # some better features

There is one repository, but I have 3 separate folders beside each other for each branch above. And make the common changes in master. then merge it with both other versions.

cd master
vim basic.cpp
git add .
git commit -m "my common edit on basic.cpp"
cd ..\version-silver
vim silver.cpp
git add .
git commit -m "my specific edit on silver.cpp"
git merge master # here i get the basic.cpp latest changes for silver project
cd ..\version-gold
git merge master # here i get the basic.cpp latest changes for gold project

Specific changes of each version will go in the corresponding folder as well, and the works on each project are isolated and IDE wouldn't be confused.

Hope that helps.

vaheeds
  • 1,568
  • 2
  • 19
  • 33
2

Totally agree with @Mot.

It's nice to hear the same questions.

Our team was also hunted for more Universal branching model than Successfull one. I.e. as @Mot mentioned above - the main idea is to avoid introducing extra repositories for supporting release-* branches in separate *.git repo as it for example is done by kernel.org for stable releases. But kernel.org does it for the sake of minimalizing of downloaded sizes I guess.

For me it seems that it's more clean to have master as mainline for develop.

Also there are some conflicts in release-* merging model to master and tagging it afterwards with idea to

use a Git hook script to automatically build and roll-out our software to our production servers everytime there was a commit on master

cause finishing (merging and tagging) is not a atomic transaction :

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2

and if git hook start build with automative versioning support:

$git describe --tags --long >.ver

then a mistaken version is possible to be built for:

$ git merge --no-ff release-1.2

I know that versioning in Successfull one introduces some bump-version process but it's not automatic.

So to sum - the key differences we introduce to branch model for releases-* merging and tagging are: - tagging release on Creating its branch - keep release's branch to enable maintainance them in future

mdn
  • 173
  • 2
  • 8
-2

The master branch should ALWAYS represent your production code base, hence you always merge the code back to master right after a production release.

Tagging is used to "memorize" the exact code which went into a production release so you can go back later and analyze the code if something went wrong.

With this theoretically it shouldn't matter if you tag your code on the release branch or on the master branch after you merged back to master. I personally prefer to tag the code on the release branch as this is exactly the code that went into the build/release (assuming something can go wrong with the merge).

The issue with the development branch concept is that it is single threaded. Brendan in this thread mentioned a strategy which could be used involving a development branch concept.

Bernie Lenz
  • 1,451
  • 16
  • 36
  • 4
    What is a "production code base" if you maintain multiple releases, e.g. v1.0, v1.1, v1.5 in parallel? – Thomas S. Jan 03 '17 at 07:07
  • Production Code Base is what is in production right now e.g v1.0. The branches carry changes for releases to be deployed to production in the future e.g. V1.0.1, v1.1 and v2.0. Once a "future" release is deployed to production it is merged back to master, so that master reflects what is in production. It is also merged forward (e.g. v1.0.1 to 1.1 and v2.0) so the v1.0.1 changes are not lost when v1.1 is released to production. – Bernie Lenz Jan 03 '17 at 14:39
  • 4
    I'm talking about maintaining multiple released versions, not about future versions. – Thomas S. Jan 03 '17 at 15:58
  • I suppose you want to see what code was released e.g 2 versions back such as v0.9? In that case you would look at the branch that was used for that release . I also find it helpful to tag the code base when you deploy to production so you can use a tag to look at previous releases. You can either tag the code on the release branch or on master after the merge. – Bernie Lenz Jan 03 '17 at 17:07
  • 4
    You seem not to understand me. Can't you imagine that in some companies multiple release versions are maintained? Microsoft, for instance also maintains updates for Windows 7, 8, 8.1 and 10, so why not other companies? – Thomas S. Jan 03 '17 at 21:56
  • 1
    That is correct Thomas. This model is geared towards products that have a single production release at a given point in time, such as e.g. web sites. I've also used this model for mobile builds e.g. android and iPhone where the build is parameterized to produce either an android or iPhone build (or both) using the same version number. I'm curious to get to know your input on how to structure a build model for a product which has multiple live versions in production at any given point in time possibly with some components shared and some components different. Please let us know... – Bernie Lenz Jan 08 '17 at 18:36
  • Another issue is if your builds spend too much time in QA. Some products cannot be automation tested and manual testing takes time. So if a bug is found in a relase in QA it needs to be fixed. But by then master branch would contain development work from the next release. We could patch qa/release branch and back merge the patch to master. but it's hard if there're conflicts. It's not enough to have the GitHub flow in that case. We need more. – Prachi Mar 23 '18 at 16:34