
The Problem with Git Flow - silasdb
https://about.gitlab.com/blog/2020/03/05/what-is-gitlab-flow/
======
dastx
I don't quite understand why people don't keep it simple. Use short lived
branches, and merge to master. Need to do a release? Master is your release.
Tag the release when it's ready. Need to make a hot fix onto the current
deployed version? Create a release branch from the tag, and then create a new
tag and merge back to master.

This combined with semver gets you far. I've yet to find any downsides with
this approach.

~~~
alkonaut
That works if

\- There is only one released version in flight at any time

\- You don't need to do a lot of validation before release. E.g. if you
release on physical media, or need certification, or shoot the program into
space and can't patch it.

Basically, it works for web software where you want (or can have) continuous
deployment.

For any scenario that _doesn 't_ do "continuous deployment", I think having
multiple release/maintenance branches is inevitable. In that case, master is
the vNext development branch, and each major version will have a branch for
stabilization/validation point releases.

~~~
berkes
Additional, practical issues that teams have to overcome, regardless of
"continuous" delivery, are:

* what is being tested by QA/Product Owner/clients etc right now? What do we do when they actually have feedback that needs fixing?

* how to keep your modifications/patches to SomeUpsTreamSoftware manageable?

* How to deal with parallel development by a team of four? Of twelve? Should all work halt until your PR is merged? What if there are conflicts? How to handle longer lived development?

All of these are hardly ever covered by "keep it simple". Turning that "keep
it simple" model into a giant mess of rules, guidelines, scripts and whatnots.
Basically a very poor version of Git flow.

Yes. Git flow is often overengineered for CD types of workflows. But it does
have all the cases and situations covered that you will eventually run into,
and that your homebuilt "simple" flow has not.

Edit: to be clear: there are solutions for all my points in your Simple
Workflow, certainly. But here's how git-flow helps:

* release-branches are ideal for putting work in front of stakeholders before release. Allowing improvements on the release. Even in a CD workflow, having something that is separated from "mainline" during the release-window is a good idea. A release-branch is just that. having a separate mainline where during that time new releases can be made is smart too: you don't want to be forced to wait for feature X to land before you can roll out some important fix. I.e. release, master and hotfix branches.

* support- branches in addition to feature branches allow easy rebasing when upstream changes and you need time to re-apply your patches and customisations. You can e.g. branch off a "support-3.1.4" off the 3.1.4 release from upstream and apply your feature/awesome-hack-x on that.

* feature branches are ideal for parallel development. Being able to merge into a branch that does not immediately release (separated from mainline) is smart, because it allows multiple team members to merge to and _then_ make a release. i.e. "development" and "feature"

~~~
Silhouette
I strongly agree with the parent comments in this thread. There are many
situations where a very simple branch strategy isn't enough.

Another one that I haven't seen mentioned yet is when your software has to be
deployed to multiple targets, and each needs the same foundation but also some
target-specific adjustments. Maybe you're going to run on different OSes and
need to use a different UI on each OS. Maybe you're writing firmware for a
range of similar products and each product has its own quirks. Maybe you need
to change some code on platform X because there's a known compiler bug where
the normal code doesn't work. There are plenty of practical circumstances
where this sort of thing can happen. You want to control and ideally automate
as much of it as you can, for the same reasons as any other deployment
process, and more complicated but systematic branching strategies are often
useful for that.

~~~
rkangel
Handling variations (e.g. multiple targets) surely isn't the responsibility of
the version control system?

If you need to build for multiple targets or have different special versions,
than write your build scripts to produce multiple versions. The Linux kernel
builds for lots of targets, but there is only one master tree for it.

~~~
Silhouette
As ever, the devil is in the details. If you're just talking about using
different build tools, sure, maybe you do that at the level of some separate
scripts. If you have mostly common code but a few relatively small adjustments
you need for each platform, where better to track that you have merged the
correct adjustments into any given build than in your VCS? If you have larger
differences between platforms, maybe you factor out parts of your code into
separate components and then build only the combination of components you need
for any given target. These strategies are not mutually exclusive.

Your Linux kernel example might be quite apt here. While the authoritative
version may have a single master, how many distros maintain their own fork of
the kernel and probably numerous other packages, merging in changes from
upstream regularly, but only ever making releases of their distro from their
own forks where perhaps they have their own bug fixes or other adjustments
applied?

~~~
rkangel
But how does ongoing development work? You have changes, now you need to merge
them into every branch. How do you know which ones are going to break the
build, how do you know which ones just aren't going to merge due to
divergence?

I have a horror of this due to having experienced a strategy where the team
took a new (subversion) branch every time they started a new project (i.e.
were building a new device in the same family). You had multiple branches with
divergent development but lots of common functionality. If you wanted to fix a
bug common to all the systems you had to fix it 4 times.

I absolutely believe that there are better ways of implementing that approach
than they used, but I also am convinced through experience that you should
have one single line of development and everything else is just 'views' on
that (e.g. point release branch is just a view master that is frozen, plus
some filtered recent history).

To take your Linux kernel example - the various forks (I'm working with the
Xilinx Petalinux Kernel now) don't really fit into the normal model. They're a
combination of a release branch and a feature branch - they take the Linux
Kernel at a certain time, then add some patches on top. _Those patches then
usually get submitted (indirectly) back to Linus so that they join the master
path of development_. That means that other people benefit from them, and
refactor them when appropriate.

~~~
Silhouette
_But how does ongoing development work? You have changes, now you need to
merge them into every branch._

Yes. That is exactly what you do.

 _How do you know which ones are going to break the build, how do you know
which ones just aren 't going to merge due to divergence?_

You use tools like unit testing and continuous integration running on all of
your key branches, just like you would on a single-master project.

 _I have a horror of this due to having experienced a strategy where the team
took a new (subversion) branch every time they started a new project_

That brings back painful memories. I think it's fair to say that in the area
of branch management, modern VCSes are much easier to use than Subversion.
Even if you're not using them as physically distributed, the same tools for
readily transferring work across branches and tracking what has gone where are
also useful in other scenarios such as the one we're talking about here.

 _I also am convinced through experience that you should have one single line
of development_

I guess this is just a case of everyone's experience being different. My
experience has been that projects that try to keep everything on a single
branch when the reality is that you will be making several significantly
different types of build over the long term can become prohibitively expensive
to manage. You don't necessarily have to use a multiple branch strategy to
deal with that, or that strategy alone; I mentioned a couple of other useful
options earlier on. But trying to use a single master and then make multiple
types of build regularly using just informal processes or ad-hoc changes on
release branches is a recipe for human error IME. _Something_ has to
systematically track and control the divergence or things get really messy.

 _They 're a combination of a release branch and a feature branch - they take
the Linux Kernel at a certain time, then add some patches on top. Those
patches then usually get submitted (indirectly) back to Linus so that they
join the master path of development._

This is exactly what typically happens in the situation I was describing as
well.

You would presumably have some root with the common code, and then you
maintain your per-target branches off that. Most development work still gets
pushed to the common root as usual, and then all targets benefit unless
they're specifically overriding the default code in that area (which is
handled at the point of merging into the target-specific branch).

Any changes first made on target-specific branches can also be passed up and
then back down onto other targets if it turns out that they are more widely
useful, or transferred directly to one or more of the other target-specific
branches but without applying the change to the common root. However,
typically you would do anything like this via some sort of cherry-picking
process; you would never normally transfer _all_ of your changes back up by
merging a target-specific branch back into the shared root.

------
wcarss
Trunk flow has a lot going for it. Here's a link in case others don't know
of/haven't heard about it -- it starts off with a tl;dr summary:
[https://trunkbaseddevelopment.com/](https://trunkbaseddevelopment.com/)

One of the key elements of trunk flow that I value about it is that "the
software you released" is not a living stream. Because of that, it should not
be tracked by a long-lived branch with commits that flow in in over time
except in rare fix situations. With trunk flow and similar styles, you can
always merge to master, and you can always deploy master. You do so by cutting
a new branch, and in my opinion, you then build a static artifact. Next time
you deploy, you cut another branch, build your artifact, and put it somewhere.

Need to do a hotfix, but there's other work since last release that you just
can't ship? Cherry-pick onto the _currently-deployed release branch_ , not
onto some long-lived production branch. There's no weird merge-backs, no
strange no-op commits in a long-lived history.

trunk-flow is also very simple. For these and other reasons, it's great.

And, some key points about building static deployment artifacts: if you build
an artifact to deploy at merge-time to master, you can avoid having your
production servers download and execute code for you. You can test your exact
artifact before you ever send it to production. You can reproduce your builds.
Left-pad-like library unavailability issues can't hit between staging and
production. Deployments to production are very fast. You can keep a few
artifacts around and roll back quickly and reliably to working states (barring
database stuff!). You can deploy two versions to different userbases at the
same time. It's very useful. :)

~~~
twic
I still cannot get my head round the fact that people don't know about TBD,
and that there are substantial numbers of people not doing it.

It's how all source control was done before DVCS. It's pretty much the default
workflow with a DVCS - if you read the Git docs and do the simplest things,
you're doing TBD! It works perfectly well for most people.

How do people get to the situation where they know about Git Flow, but don't
know about TBD? This feels like a huge failure of education or documentation
or something.

~~~
pseudalopex
Trunk based development isn't how all source control was done before DVCS.[1]
The Git documentation suggests using long running branches.[2] "A successful
Git branching model" was very influential. Git Flow sounds official. GitHub
Flow sounds like Git Flow.

[1] [https://trunkbaseddevelopment.com/alternative-branching-
mode...](https://trunkbaseddevelopment.com/alternative-branching-
models/index.html#mainline)

[2] [https://git-scm.com/book/en/v2/Git-Branching-Branching-
Workf...](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows)

------
jdlshore
Martin Fowler wrote a _superb_ discussion of branching strategies. It's here:
[https://martinfowler.com/articles/branching-
patterns.html](https://martinfowler.com/articles/branching-patterns.html)

------
viraptor
I've got strong feelings about git-flow, but I think the main thing all these
"generic flow" solutions are missing is: what are your project requirements?

Some projects need release branches, some projects use continuous deployment,
some projects need manual QA, etc. There is no solution that will work for
everyone, so unless your flow description starts with assumptions and matching
requirements, it's wrong. (for some people reading about it)

~~~
tempodox
This one is an ad for a payed service, so one can't expect a broad take on the
subject. The usual “caveat emptor” applies.

~~~
viraptor
I slightly disagree. It doesn't cost anything to prefix: "There are many ways
to approach it, which will differ depending on your needs. Here's a solution
which we believe will work for most, so we want to name it and make it simple
for you to apply." It doesn't take anything away from the rest of the content.

------
dragonwriter
What a clickbaity title; there's no substantial discussion of Git Flow at all;
the paragraph they actually spend discussing two minor issues sounds like it
was written by someone who has never done serious work in Git Flow.

Should be titled “The sales pitch for GitLab Flow”.

------
danw1979
> Git flow forces developers to use the develop branch rather than the master.

No it doesn’t.

> Another frustrating aspect is hotfix and release branches

I beg to differ.

I know what would be frustrating though:

> GitLab Flow is a way to make the relationship between the code and the issue
> tracker more transparent. Each change to the codebase starts with an issue
> in the issue tracking system.

... tying my repo to one particular git hosting platform.

------
sn1de
I honestly thought they were finally renouncing GitLab flow as a massively
misguided idea. They are both flawed. You shouldn't be using branches in your
version control system to denote stages in your development process or
deployment targets. It totally breaks down when you move to CICD, which should
be your goal. Trunk based is the way to go. These git flow things persist
because that is what the search engines puke up when people google for git
branching.

~~~
aidenn0
CD doesn't work for many types of software; it's not uncommon for customers to
want only bugfixes (or even security bugfixes only), and that means branches.

------
servilio
There is a need for simplified workflows, but this sounds and looks like an
exercise in brand marketing more than a good analysis on how to offer a better
Git workflows.

> Git flow forces developers to use the develop branch rather than the master.
> Because most tools default to using the master, there’s a significant amount
> of branch switching involved.

I'd like to see this fleshed out, since whatever branch naming convention or
roles you use, you will be switching the same amount.

> Another frustrating aspect is hotfix and release branches, which are
> overkill for most organizations and completely unnecessary in companies
> practicing continuous delivery.

Yes and no. If you don't separate master from develop, hotfix branches just
work like feature branches. But if you need them separated, then...

> Bug fixes/hot fix patches are cherry-picked from master

Avoid doing this, use daggy fixes[1], and it will make it breeze to check that
a fix was actually merged and where[2]. And if you do cherry pick, at least
use "-x".

[1] [https://wiki.monotone.ca/DaggyFixes](https://wiki.monotone.ca/DaggyFixes)

[2] git branch --contains <commit>

------
bredren
I am a fairly committed practitioner of git flow on multiple projects.

The problem of not easily linking feature branch names to issues is real,
though I have been solving this using:

`[issue id]/feature-or-issue-title-abbreviated`

And while you don’t get nice hyperlinking from the branch references on
GitHub—-and it’s possible for the issue title to be out of sync with the
feature branch name at times, it isn’t too bad and I don’t often need to go
back and look at a feature branch.

Perhaps projects with bigger teams this is more important and the linking /
strong issue attribution to the branches is more meaningful.

I’m less clear on the removal `develop`. It makes more sense to me to use
master as this serious “released” state. And for develop to be a bit more
loose.

More importantly, I typically will run `develop` on a staging instance. So
it’s pretty important to me.

I still do testing on ‘develop’ and feature branches before they are merged. I
also don’t feel like the start / finish release process is all that onerous.

From a commercial standpoint, I’m not a huge fan of tossing GitLab into the
concept name. It’s a little brand-y on something that just doesn’t need it.

~~~
jlgaddis
> _From a commercial standpoint, I’m not a huge fan of tossing GitLab into the
> concept name. It’s a little brand-y on something that just doesn’t need it._

I imagine it's meant to be a response to "GitHub Flow" [0].

\---

[0]:
[https://guides.github.com/introduction/flow/](https://guides.github.com/introduction/flow/)

------
ablanco
I don't think this is a problem with git-flow, it's more a problem of using
git-flow when you don't need it.

I use git-flow on projects that need to be installed by various different
clients and there's no way to force all of them to migrate to the latest
version, so you have to maintain support for older releases.

When the software needs to be installed in a single place and you can do it
with CI/CD theres no need for the git-flow complexity.

------
ramenmeal
I'm not a fan of merging master -> production for deployments. This means that
what you tested in master may not be the same artifact that is deployed to
prod. You're relying on people to correctly handle merge issues in git. This
can become an issue if you have some complex hotfixes that have to happen.

edit: I'd rather trunk based w/ tagging commits for releases.

~~~
donmcronald
Yeah. I wonder if that merge to production rebuilds artifacts. That seems
nasty.

------
somewhereoutth
I feel a whole lot of problems would just go away if merge was abandoned. Thus
every 'merge' would require a rebase (and subsequent deletion of the merged in
branch), and branches stay as branches. For example it then becomes obvious
and inevitable that hotfixes must be on an independent maintenance branch
(cherry picked in/out of the master if appropriate). There is no longer the
proliferation of merged in feature branches - only features currently worked
on (and yet to be rebased) would have a branch. There is no concept of release
vs master vs dev as it is not possible to merge one into the other. Push/pull
is fast forward or force rebase.

Easy enough to write a wrapper around git to do this - I am tempted.

------
polymeris
On the topic of Git Flow and simpler & faster alternatives, last month I
published a short blog post about my experience learning those alternatives
exist at CircleCI[1].

The most important learning for me was that things like Git Flow aren't free:
they slow you down and make developers feel more detached and less responsible
for the code that's running in prod.

[1] [https://circleci.com/blog/you-are-what-you-git-how-your-
vcs-...](https://circleci.com/blog/you-are-what-you-git-how-your-vcs-
branching-model-affects-your-delivery-cadence/)

------
alkonaut
I immediately spot one huge issue with this

> The production branch is essentially a monolith – a single long-running
> production release

It assumes that only one version is deployed at a time, so you can't really
service version1.0 after you shipped version2.0.

Having multiple independent maintenance branches for production is critical
for any branch pattern that should apply to both web software (normally single
deployed version) and e.g. Desktop (normally multiple deployed versions).

Th

------
steve_taylor
This is idiotic. Different situations call for different workflows. Working in
a corporate environment with planned, infrequent releases? Use Git Flow. Doing
continuous delivery instead? Use the feature branch workflow.

This smells like GitLab trying to increase its ownership of the ecosystem.

------
tupac_speedrap
How is git flow complicated? I feel like some developers are doing shonky
stuff with git branching and then blaming it on the branching strategy.

If you used a system with less use of branches you'd just end up with dodgy
code in master instead.

------
einpoklum
My problem with this suggestion is, that I tend to do history rewrites on the
development branch, if I realize I've fucked something up; but I don't do that
on master. So on master, broken things get fixed with a new commit; on
development - sometimes, sometimes they get fixed retroactively.

That means that you can safely "git pull" the master branch, always, into the
future, but if you try to pull the development branch, you may well fail.

------
jjuel
Am I missing something or is this pretty much Gitflow with develop being named
master and master named production? Maybe I don't fully understand Gitflow or
we are using it like Gitlab Flow already with different names.

------
somewhereoutth
I think this sort of thing might become much more tractable if it were
possible to visualize a git repo _as it actually is_ \- i.e. a directed graph
of commits (occasionally with two parents - a merge commit), with moving
labels (branch names) and fixed labels (tag names). Like when you buy a small
shrub from the garden centre and it has a label attached to it somewhere.

Pushes and pulls can then be visualized as two such shrubs reconciling
themselves.

~~~
nicky0
Interesting analogy, but as a gardener, I've never encountered the concept of
a shrub reconciling itself so I have no idea what this visualization reveals!

~~~
somewhereoutth
Imagine a shrub made of shrub A and shrub B. Parts of the shrub (from the
root) are from both, parts are from A only, and parts are from B only. Imagine
also the 2 sets of labels from A and B. It would become clear how the
push/pull is updating its target shrub, and indeed if and what bits of the 2
shrubs (or their labels) conflict.

------
rob74
Interesting tidbit: according to the "SEO-friendly" URL, the title should
actually be "what-is-gitlab-flow" \- I wonder if that was also the original
title of the article, before it was changed into something more "clickbaity"?

------
pronoiac
> run _all_ tests on all the commits

That gave me pause; I'm used to relatively small commits, for easier review
and verification, so that seemed too much. Reading the link, I think they
mean, run tests on every branch on every push.

~~~
romanr
In Gitlab you can add “ci skip” to commit message to skip CI run

------
sebazzz
We currently use a simplified version of gitflow. Essentially we picked only
the master, develop, and release branches from it. Of course we do have
experimental branches but all nowhere as complicated as gitflow.

------
thisisastopsign
Sometimes I feel there should be a survey for Git methods and people vote on
it. Repeat annually. Eventually we'll settle the debate

------
king_magic
I've literally never had a problem with Git Flow, nor have any developers I've
worked with. It's fine.

------
WWLink
Between monoliths, this discussion, and other complaining about git I see
around here, I wonder just how many of you are using subversion lol.

~~~
sidlls
git's got some great features for very basic development workflows and the
fact that it's distributed is undeniably a significant advantage.

What amuses me, though, is all the ceremony and patterns in the use of git
that restrict its use in ways that are sort of pale reflections of subversion,
P4 and similar version control systems.

~~~
WWLink
I like the distributed nature of git, the ability to make local commits, jump
airgaps with bare repos, submodules, shallow clones, all kinds of silly things
I suppose. I won't lie, I don't have a ton of experience with subversion, but
whenever I've used it, it felt incredibly limiting.

------
hellofunk
Trunk-based development FTW!

------
malinens
the problem is that gitlab works very bad with other git flows and they are
ignoring issues about them so they force their own flow sadly...

I still enjoy working with gitlab but this annoys me very much

------
0x00101010
man gitworkflows

------
renewiltord
Gonna be honest with y'all. You don't need a git workflow. Seriously, YAGNI.
Deploy every `master`, no other restrictions.

Git workflows are over-engineering.

~~~
AlphaSite
That works if you have a deploy step. There’s a world beyond SAAS. A very
lucrative one.

~~~
renewiltord
Oh that's entirely fair. I was 100% thinking SaaS because of the website we're
on, but if you do have to maintain multiple versions for whatever reason,
you're going to need a complex flow with multiple trunks.

~~~
kingosticks
I don't see how SaaS is immune to this. You could easily find yourself with a
big customer that effectively wants their own deployment and doesn't want
updates (new bugs / big changes) but still demands occasional fixes/features
that you often want to also merge into the main deployment.

~~~
renewiltord
It's not immune since few things in life have a measure zero or measure one
probability. It is unlikely, though, imho.

