Skip to content. | Skip to navigation

Personal tools
Log in
You are here: Home


Showing blog entries tagged as: version control

Against The Flow

Posted by Manuel Reinhardt at Jun 17, 2016 10:45 AM |
Filed under: , ,

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.