In our company we're using git a lot. We've started practising Git
Flow
for some of our larger projects. Recently, an article about GitLab
Flow
(with comparisons to Git Flow and GitHub Flow) got me thinking whether
Git Flow is the right flow for us. Two problems with Git Flow that the
article mentions immediately struck a nerve with me:
* it's quite complicated
* it deviates from the convention that master is the default branch
The second issue is easily addressed by simply using a different name
for the branch that holds the release tags (say, "production"). The
Git Flow extension even lets you configure that ("git flow init").
The first one is not so easily remedied, though. You have to remember to
merge feature branches to develop, hotfix branches to master and
develop, etc. It gets easier if you're using the Git Flow extension,
but the commit history is still full of merge commits that don't add
much information. Also, if you're using a release helper like
zest.releaser in addition, it adds more steps to the process which can
create additional confusion. And, even with the Git Flow extension,
mistakes happen and can be hard to resolve.
GitHub
Flow
is on the other end of the spectrum in terms of complexity. It boils
down to doing development in feature branches and merging them back to
master (after review).
GitLab
Flow
occupies the middle ground. It defines a production branch that reflects
deployable code. When you want to make a release you merge master into
production. Nothing else is done on "production" and it is never
merged to any other branch.
You can add optional branches that hold code deployed to separate
environments (demo, staging, etc.). There's also a concept of release
branches but that doesn't seem relevant to us.
The second half of the article (starting from "Merge/pull requests with
GitLab flow") is mostly concerned with integration of the git workflow
into issue tracking. That's an interesting topic as well but I'll
stick to the actual git workflow for now.
To decide whether one of these flows is appropriate for us we need to
ask, of course, what we need vs. what they offer. The basic idea is of
course to get to a deployable state in a quick and sane fashion. Feature
branches probably make sense for all our projects to keep things
separate until they are ready to share. So, do we need more than that?
All of the mentioned workflows seem to assume that continuous deployment
is practised, or at least that code is deployed via git checkout. I
remember learning, ages ago, never to deploy from version control. But
times change and it seems to be quite common by now to do just that. In
fact, part of the intention of the discussed workflows seems to be to
define a safe way of deploying directly from git. In our company we
haven't adopted that approach yet, but we might think about doing so
for some projects, at least for the code that never gets released to the
public anyway. It would of course eliminate the overhead of creating
eggs.
If we stick to creating eggs for now, though, I don't see much benefit
of having a separate branch only for deployable versions, be it called
"master" or "production" or whatever. This seems to suggest using
GitHub Flow.
However, we sometimes have the situation that we have long-running
branches for bigger development packages that the customer wants
deployed in one go, not bit by bit. At the same time we will still have
small help desk developments or bug fixes in parallel using more
frequent (e.g., weekly) deployments. This is addressed by Git Flow by
having a dedicated "develop" branch where long-running development can
happen and that receives any helpdesk/bugfix commits which happen in the
hotfix branches. However, this is where a lot of the complexity comes
in.
Can we simplify this a little? The need to merge hotfix branches into
develop in addition to master seems to arise from the fact that the
develop branch is always continued. Alternatively we could say that we
create dedicated branches with a finite lifetime for every development
package. E.g. in one of our projects we usually have quite some time in
between each development phase, so it doesn't make much sense to keep
the develop branch open. Instead we would create a named branch ("p8",
"phase2", ...) off master, and once the package is finished we merge
back to master and delete that branch. If anything else has happened on
master in the meantime it will be in the release because the release is
created from master. The next development branch will be branched off of
master again, so it will have those commits as well.
Or we could even always use "develop" as the development branch name.
There's no problem with merging develop to master and deleting it, and
then later creating a new branch that's called "develop" again. Of
course this doesn't work if there are multiple development packages in
progress at the same time, but that's probably not a good idea anyway.
The advantage of reusing the branch name is obvious - you always know
what the current development branch is called.
Maybe this could become the basis of a simplified Git Flow for projects
where we need it: Regular smaller development (like help desk and bug
fixes) on master, larger packages on named branches (could always be
named "develop"); plus feature branches that branch off and merge back
to either. Some convention may be helpful to mark which branch merges
back to master and which to the development branch.
I feel we should also talk about the review process when merging a
feature branch, but before I get carried away any more I'll stop here.
There's no doubt that there is no such thing as the universally best
workflow. That's why I mentioned looking at our different projects -
different projects may call for different workflows. However, my hope is
that we could find or come up with a modular workflow (like GitLab Flow)
and simply ignore some optional parts for our simpler projects while
taking advantage of the more advanced workflow features for projects
that need a little more structure.