Git Flow

In which I briefly pontificate on the Git-Flow Workflow.


GitFlow isn’t a “crunchy” thing that requires tooling, but, rather a “fluffy” convention that requires adherence by team members. Consequentially; it applies to other tools and quite nice regardless.

In effect;

  1. one always starts a feature-branch from master with a specific feature in mind
  2. one commits and works within that feature-branch only until complete
  3. one merges master into the branch, then, open a pull-request
  4. team leader (or whomever) will merge the feature-branch

GitFlow

Here’s a big picture …

Fancy

… but that’s complex!

A step-by-step guide follows.

First, the system’s history is as below; just the master branch.

graph TD;
	old[... ancient history ...]
	def0[initial master]

	old --> def0

A developer (or team lead wearing a developer’s hat) decides to implement FeatureA so opens the feature-a branch.

graph TD;
	old[... ancient history ...]
	def0[initial master]
	feata0[Feature A Branch]

	old --> def0

	def0 ==> feata0

Development proceeds and the developer commits tests, changes, and documentation in some order.

graph TD;
	old[... ancient history ...]
	def0[master / initial]
	feata0[Feature A / Branch]

	old --> def0

	def0 ==> feata0
	feata0 --> fetad[Featuer A / Documentation]
	fetad --> fetat0[Featuer A / Tests]
	fetat0 --> fetai[Featuer A / Implementation]
	fetai --> fetat1[Featuer A / More Tests]
	fetat1 --> fetaC[Featuer A / Complete!]

In the meantime, however, the team has made some updates themselves; master has moved on!

graph TD;
	old[... ancient history ...]
	def0[master / initial]
	feata0[Feature A / Branch]

	old --> def0

	def0 ==> feata0
	feata0 --> fetad[Featuer A / Documentation]
	fetad --> fetat0[Featuer A / / Tests]
	fetat0 --> fetai[Featuer A / Implementation]
	fetai --> fetat1[Featuer A / More Tests]
	fetat1 --> fetaC[Featuer A / Complete!]

	def0 --> def1[master / fixed line endings]
	def1 --> def2[master / spelling corrections]

This is fine

This is fine; the dev just merges master back into their branch, then opens a pull-request to have their branch merged into master.

graph TD;
	old[... ancient history ...]
	def0[master / initial]
	feata0[Feature A / Branch]

	old --> def0

	def0 ==> feata0
	feata0 --> fetad[Featuer A / Documentation]
	fetad --> fetat0[Featuer A / / Tests]
	fetat0 --> fetai[Featuer A / Implementation]
	fetai --> fetat1[Featuer A / More Tests]
	fetat1 --> fetaC[Featuer A / Complete!]

	def0 --> def1[master / fixed line endings]
	def1 --> def2[master / spelling corrections]

	def2 -.->|merge updates|fetaC

	fetaC --> pr>Feature A / pull request]

Finally; the team lead either approves or rejects the pull request.

… or, maybe the team’s server runs checks and merges the branches when they pass.

Policies differ - tools like GitLab “protect” certain branches like master to enforce this. Additionally; tools and support exist to make the results of testing obviously to the “team leader” who is performing the merge.

But Why

But why?

Basically … “because” is the main reason, the other is that no “real” alternative seems to exist.1 The naive alternative (which all the frikkin undergrads do) is to always do all work in master and do it in sequence, rather than parallel.

True Story

This is bad and won’t work well in real life, because the whole team has to coordinate work outside of VCS. In effect; it’s turning dVCS into a file-sync tool … which is kind of a waste.

As a final appeal to authority … Facebook does it. Specifically, their Phabricator tool seems designed to asses metrics from branching, such as this.


  1. … as far as I know. If you’re from the future … tell me?

    [return]
comments powered by Disqus
Peter LaValle avatar
Peter LaValle
Any links probably include affiliate ids for that sweet sweet kickback - and some programs require that I tell you. The contents of this blog are likely unrelated - as they include games, paints, and build tools.