BeeFlow is a streamlined git branching model with a clear focus on readability of the history and completely avoids merge commits. Using BeeFlow is most useful in projects with the following requirements:
- Human readable history
- Maintaining multiple versions in parallel
This section gives an overview of BeeFlow and explains the fundamentals on a very high level. More detailed explanations can be found in the subsequent sections. Working with BeeFlow only requires three kind of branches:
- Topic branches: A topic branch contains commits related to a feature or a bug fix, which are not yet completed or reviewed.
- Master branch: The master branch contains completed features which are not yet released.
- Release branches: A release branch exists for every major version of project.
The example below shows how these branches interact with each other. In general every topic
branch branches off from HEAD
of the master
branch. The master
branch always branches off from the HEAD
of the latest release branch. Every commit that represents a released version is tagged.
A---B---C topic-a
/
D---E---F master
/ \
/ `G---H topic-b
/
---I---J---K 1.x
: :
v1.1.0 v1.2.0 Tags
Notice, the topic-b
branch in above example is not branched off from F
, because when it was created E
was HEAD
of master
. A rebase is only required before it is merged into the master branch.
Each new feature should reside in its own topic
branch. A new topic
branch that branches off from master
branch can be created with the following command:
git fetch
git checkout -b my-feature origin/master
On this branch, the new feature can be build up. In theory, it is possible to construct the new feature from several commits. However, in order to ensure the reviewability of a feature, it is strongly recommended that the features are kept as small as possible so that they - ideally - fit into one commit. This not only improves the readability of the project history, but also makes it a lot easier to rollback a feature. In case that it is not possible to construct the feature within one commit it is recommended to prefix the subject of the commit message with a feature related tag. This makes it very easy to identify related commits.
An example history would now look like this:
A my-feature
/
B---C---D master
/
---E---F---G 1.x
: :
v1.1.0 v1.2.0 Tags
When the feature is considered as ready by its owner, the topic
branch can be merged (fast-forward only) into master
. If the topic
branch is called my-feature
, this can be done with the following commands:
git fetch
git checkout -b master origin/master
git merge my-feature --ff-only
After applying these commands the history should look like this:
B---C---D---A master / my-feature
/
---E---F---G 1.x
: :
v1.1.0 v1.2.0 Tags
Now the new master
branch can be pushed and the topic
branch my-feature
can be deleted.
The fast-forward merge will fail, if the topic
branch (my-feature
) is not rebased onto the master
branch and the history looks for instance like this:
A my-feature
/
B---C---D master
/
---E---F---G 1.x
: :
v1.1.0 v1.2.0 Tags
In this case it is required to rebase the topic
branch onto the master
branch with the following command:
git checkout my-feature
git rebase -i --onto origin/master
When the rebase was successful, retry to merge the feature into master.
When a new release is due, either because of a predetermined release date or because master
branch has acquired enough features, the following steps apply:
-
Identify the commits on the
master
branch which should be part of the release (A
andD
in below example).A---B---C---D master / ---E---F---G 1.x : : v1.1.0 v1.2.0 Tags
-
Re-order releasable commits on
master
and push to new branchmaster-rel-<new-release-version>
. Verify that all tests pass on the new branch after the rebase. If all tests pass this branch can be force pushed to the upstreammaster
branch and deleted afterwards.A---D---B---C master / ---E---F---G 1.x : : v1.1.0 v1.2.0 Tags
-
Now the commits to release have the desired order and it is possible to merge them (with fast-forward only) into the release branch
1.x
. This can be achieved by the following commands:git checkout -b v1 origin/v1 git merge <commit 'D'> --ff-only
After applying these commands the history should look like this:
B---C master / ---E---F---G---A---D 1.x : : v1.1.0 v1.2.0 Tags
Push the updated
HEAD
of1.x
branch to the upstream1.x
branch.git push origin HEAD:refs/heads/v1
-
Trigger the build process which tags the
HEAD
of the release branch1.x
. After a successful build the history should look like this:B---C master / ---E---F---G---A---D 1.x : : : v1.1.0 v1.2.0 v1.3.0 Tags
First it is required that the commit representing the patch that fixes the bug is merged into master. In the example below the commit A
contains the patch.
A master
/
---B---C---D 1.x
: :
v1.1.0 v1.2.0 Tags
Maybe it is possible to simply release a new version 1.3.0 that contains the fix and don't fix the already released versions. In this case have a look into the section Release new features.
But in most cases it is also required to down port the patch to already released versions. This can be achieved by the following steps:
-
Checkout the version to be fixed and create a new bugfix branch.
git fetch git checkout -b bugfix-<name>-<new_version> origin/<version_to_be_fixed>
Example: The patch represented by commit
A
fixes aNullPointerException
during the bootstrap phase and should be fixed in version 1.1.0.git fetch git checkout -b bugfix-bootstrap-NPE-v1.1.1 v1.1.0
-
Cherry-pick and push the commit representing the bug fix.
git cherry-pick <commitID> git push HEAD:refs/heads/<bugfix_branch>
Example: Commit
A
with the id4f1a16e6
contains the bug fixgit cherry-pick 4f1a16e6 git push HEAD:refs/heads/bugfix-bootstrap-NPE-v1.1.1
Now the history should look like this:
A master / ---B---C---D 1.x :\ : : `-----:-------A' bugfix-bootstrap-NPE-v1.2.1 : : v1.1.0 v1.2.0 Tags
-
Trigger the build process which tags the
HEAD
of the bugfix branch with a new patch version and delete the temporary created bugfix branch. This should result in a history like this:A master / ---B---C---D 1.x :\ : : `-----:-------A' : : : v1.1.0 v1.2.0 v1.1.1 Tags
BeeFlow recommends to use the Semantic Versioning Specification (SemVer). In BeeFlow every major version has its own branch. It is recommended to name this branches 1.x
, 2.x
, ... The HEAD
of these branches should always point to the commit representing the latest minor version of the related major version. Every commit that represents the release of a version must be tagged. It is recommended to use the version identifier as name for this tag e.g.: v1.0.0
, v1.1.1
, ... . In case an already released minor version must be patched, because of a bug fix, the commit representing the patched version is only referenced by its mandatory tag. Applying these rules make the history looking like this:
----A-----B----C----D 1.x
:\ :\
: `-----C' : \
: : : `----E-------F 2.x
: : : : :
: : : : :
v1.1.0 v1.1.1 v1.2.0 v2.0.0 v2.1.0 Tags