Git Workflow

The Main Branch

This workflow uses one main branch, master. This branch is the main, eternal branch and will always represent the latest, stable version of the code. Commits are not allowed to be directly pushed to this branch.

The Release Branch

The release branch is branched from the head of the master branch as soon as new work starts on the next release version. Features for the next release are developed in feature branches and rebased on top of this branch. This branch is named release/next and there can only be one of these branches at any given time.

Release branches are almost always pushed to the remote due to their longer-lived nature.

The reason temporary release branches are used, as opposed to a second eternal branch like develop, is so the current release branch can be easily updated when a hotfix or docs branch is integrated into the master branch, while keeping the history linear and clean.

Creating the Release Branch

$ git checkout -b release/next master

Updating the Release Branch

Keeping the release branch current is as simple as rebasing on master any time master changes.

$ git checkout release/next
$ git rebase master
$ git push --force-with-lease

Finishing the Release Branch

$ git checkout release/next
$ git rebase -i master
$ git checkout master
$ git merge --ff-only release/next
$ git push origin master
$ git branch -d release/next

By using rebase instead of merge --no-ff, the linear history keeps the master branch clean and offers the opportunity to clean up the release history before integration.

If the release branch exists on remote, which it almost always should, remove it.

$ git push origin :release/next

At this time, the release must be versioned by using the version tool to bump the version file and tag.

$ version set version

Feature Branches

New feature branches are branched from the head of the release branch and are short lived branches where the majority of work takes place. They are used to develop new features and bugfixes for an upcoming release. Feature branch names are prefixed with feature/ and will look similar to feature/the-feature. Feature branches exist only in the developer's repository and usually only pushed if the feature will take a long time to develop, as a backup precaution.

Feature branches are used instead of direct commits to the release branch in order to allow multiple features to be developed simultaneously. If a feature's development becomes blocked, development in other areas can continue cleanly.

Creating a Feature Branch

$ git checkout -b feature/the-feature release/version

Updating a Feature Branch

Updating a feature branch is done with rebase similar to updating the release branch.

$ git checkout feature/the-feature
$ git rebase release/version
$ git push --force-with-lease

Finishing a Feature Branch

$ git checkout feature/the-feature
$ git rebase -i release/version
$ git checkout release/version
$ git merge --ff-only feature/the-feature
$ git push origin release/version
$ git branch -d feature/the-feature

If the feature branch was pushed to remote, it will need to be removed.

$ git push origin :feature/the-feature

Hotfix Branches

Hotfixes occur when a critical failure is exposed in a released version and fixing the bug in the next release would take too long for users to get the fix. Hotfix branches are extremely short-lived branches branched from the master branch. These branches are named hotfix/fix.

A hotfix will always increase the patch version.

Creating a Hotfix Branch

$ git checkout -b hotfix/fix master

Updating a Hotfix Branch

Hotfix branches are so short-lived, they shouldn't ever need to be updated. If a hotfix branch needs to be updated, it likely means that a release branch was integrated into the master branch, and it has the same bug the hotfix is currently fixing. This is just stupid.

If you must update a hotfix branch, rebase it on top of master.

$ git checkout hotfix/fix
$ git rebase master

Finishing a Hotfix Branch

$ git checkout hotfix/fix
$ git rebase -i master
$ git checkout master
$ git merge --ff-only hotfix/fix
$ git push origin master
$ git branch -d hotfix/fix

At this time, the patch release must be versioned by using the version tool to bump the version file and tag.

$ version set version

The final step is to update the release branch by rebasing it on master. See: Updating the Next Release Branch.

Documentation Branches

Sometimes the documentation in the master branch needs to be edited.

Documentation branches are treated the same way as hotfix branches, with two exceptions: they are named docs/the-change and they do not increment the master branch version.

Final Branches

Final branches are feature-frozen branches, or branches for final versions that will not receive any new feature development, but will continue to receive hotfixes. These branches, named final/version, are branched from master before moving into development for a new Minecraft version. For example, the final branch for Minecraft 1.12.2 looks like final/1.12.2.

Hotfixing a final branch works the same way as hotfixing the master branch. If a hotfix to a final branch is applicable to the master branch, create a hotfix branch from the master branch and use git cherry-pick to apply the relevant commits to the master->hotfix branch, then finalize the new branch. Version tags created from a hotfix in a final branch should never make their way into the master branch.

Final branches are never rebased, finalized, or deleted.

Creating a Final Branch

$ git checkout -b final/version

Alpha Releases

Alpha releases are compiled and released from the current release branch.

First, tag the branch using the next release version number and the alpha suffix:

$ version set 1.0.0-alpha0

Then compile and release:

$ gradle clean build