There are a lot of people explaining GitFlow in different blog posts and videos. I could not find one that, using the correct arguments, explained when it should, and should not, be used. I would say its a very simple choice. These are my personal opinions and you don't have to agree =)
GitFlow is really the simplest thing. People saying that its over-engineered are using it wrong. People that are moving away from it should probably not have used it in the first place. If you don't feel that its simple, then its not the right pick for you.
If you don't have a code freeze, then GitFlow is not for you! Let's divide the people working with the project into developers and configuration manager(s) and look at what they do.
GitFlow as a developer
As a developer you have 2 kinds of branches.
- develop Integration branch. Refers to the next release.
- feature/X Feature branch where feature X is developed.
You may have feature branches that branch out of other feature branches. In order to, easily, collaborate with other developers on a feature.
- You should always merge code to develop as fast as you can. To avoid merge conflicts.
- You should regularly rebase or merge develop into you branch. To avoid merge conflicts and benefit from new improvements like refactorings.
To work on the next release. You branch out of develop, work with the feature, merge back to develop.
* (develop) Merge branch 'feature/work-with-correcting-a' into develop |\ | * (feature/work-with-correcting-a) Correcting a |/ * Merge branch 'feature/work-with-a' into develop |\ | * (feature/work-with-a) a |/ *
To work on the next-next release, or even further into the future, simply don't merge it back to develop before next-next is next. And keep in mind, it may be a good idea to merge it into develop earlier, to avoid merge conflicts, if you can do feature toggling.
As a developer, this is all there is to it! This is how developers most often prefer to work. Just look at any open source repository. Most often you fork the main repository and the master in your fork is your feature branch. But still, this is as simple as it can get and this is how developers do it!
And again, if you don't have a code freeze then don't use GitFlow. You will most likely not have develop-branch but instead just master. And you will also most likely do releases directly from master.
GitFlow as a configuration manager
As a configuration manager you have 2 kinds of branches.
- master This is the what's in production.
- release-X This is what's included in release X.
As soon as it's code freeze it's time to create the first release candidate. That is done by branching out of develop into release-X. The version of develop is now set to 1.1, in Java that would mean changing the version to 1.1-SNAPSHOT while in the release branch its still 1.0-SNAPSHOT. The semantics of the versions is a side track, but I can recommend this blog post.
| * (release-1, tag: 1.0-RC-1) Releasing RC 1 | * Setting version to 1.0-RC1 * | (develop) Setting version to 1.1-SNAPSHOT |/
The release candidate, RC1, is deployed and tested and if it's all good then it's released. But there is probably something that needs to be fixed. It can be done in different ways.
With cherry-picking from develop.
This is the prettiest but it may also not be possible. Merge conflicts may hinder this. There is also a risk that the develop-branch is too far ahead making it hard to know if the fix will work once it's in the release-branch. But I feel that it gives the configuration manager the most control of the release process.
With merging a feature-branch that branches out of the release-branch.
This often my preferred choice in large teams. It gives the configuration manager control of what's included in the release. It avoids risk of merge conflicts. The tests done on that feature-branch can be trusted. It can be done with pull requests.
With direct commits to the release-branch.
This may fit a technical team where the configuration manager is also a developer. It provides a release process for the current release and enables the developer to work on the next release in develop. It lacks support for code review but you may not need that in a small project.
Here is what it may look like if cherry-picking is used.
| * Setting version to 1.0-SNAPSHOT | * (release-1, tag: 1.0-RC-2) Releasing RC 2 | * Setting version to 1.0-RC2 | * Correcting a | * Setting version to 1.0-SNAPSHOT | * (tag: 1.0-RC-1) Releasing RC 1 | * Setting version to 1.0-RC1 * | (develop) Setting version to 1.1-SNAPSHOT |/
Now if RC2 is good and should be released then that exact artifact is deployed in production.
- release-1 is merged into master to keep track of whats in production.
- master is merged into develop to make sure any changes made in production are also in the next release.
I've shown the two roles in GitFlow and I hope I made it obvious that its actually a very simple workflow! It will not fit all projects. A tiny library that is just used by other software will probably not gain from using GitFlow. A big application, where a release is the same as a production deployment, will probably gain from using GitFlow.