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;
- one always starts a feature-branch from
master
with a specific feature in mind - one commits and works within that feature-branch only until complete
- one merges
master
into the branch, then, open a pull-request - team leader (or whomever) will merge the feature-branch
GitFlow
Here’s a big picture …
… 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; 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
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.
- https://nvie.com/posts/a-successful-git-branching-model/
- https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
- https://datasift.github.io/gitflow/IntroducingGitFlow.html
… as far as I know. If you’re from the future … tell me?
[return]