This document provides a clear and versatile Git workflow that teams can use to collaborate on projects. We call this workflow the Git+Hub Flow, which combines the advantages of both the Github Workflow for continuous deployment and the Gitflow Workflow for release deployment.
Note that continuous deployment is a strategy where features are deployed as soon as they're ready, while release deployment is a strategy where features are bundled into a release and then deployed all at once.
If you're unfamiliar with the most commonly used Git workflows, we highly recommend reading the following articles in the given order. This will help you understand where the Git+Hub Flow fits in and the potential advantages it offers:
- http://scottchacon.com/2011/08/31/github-flow.html
- https://nvie.com/posts/a-successful-git-branching-model/
- https://martinfowler.com/articles/branching-patterns.html
So, what is the Git+Hub Flow?
-
Anything in the
mainbranch is deployable (the continuous part). -
The
release-vX.Ybranch is a copy ofmainat a specific point in time (the release part). -
To work on new features or changes that need to be made to
main(excluding bug fixes), create a branch off ofmainwith a descriptive name. This name should typically include the name of the team involved at the beginning of the branch name. For example,senior-devs/ui-upgrade, orjunior-devs/ui-upgrade. If a single person is making the change, they can create a branch with no team name, optionally including their name, such asjohn/ui-upgradeor simplyui-upgrade. -
Once changes have been merged and pushed to
main, the feature branch should be deleted, and you can deploy immediately if necessary. -
At a periodic interval or based on stated time or how the software is released, create a branch from
mainnamedrelease-vX.Yand tag it as a stable release. -
If a bug is found in
main, create a branch from it and name ithotfix-main#<ID>. After fixing the bug, mergehotfix-main#<ID>intomain, and delete the hotfix branch. -
If a bug is found in
release-vX.Y, create a branch from it and name itbugfix-vX.Y#<ID>. After fixing the bug, mergebugfix-vX.Y#<ID>intorelease-vX.Y, and delete the bugfix branch. Note that, depending on the severity of the bug, if it is critical and there is a possibility of it also existing inmain, then ahotfix-main#<ID>branch should be created frommain. The bug should also be fixed in this branch, while taking into account the changes that have occured betweenrelease-vX.Yandmain. Once completed, thehotfix-main#<ID>branch should be merged intomainand then deleted. -
In summary, at its core, the central repository will always have two main branches with infinite lifetimes:
mainfor the unstable deployable release andrelease-vX.Yfor the stable deployable release. For projects that provide maintenance, fixes, backport, etc. for releases other than the current stable release, there can be more than onerelease-vX.Ybranch. -
When compared to the stable
release-vX.Ybranch, the main branch is considered unstable. This is because new features and changes are frequently added to it without prior notice to project users, which could potentially break existing functionality or user interactions. In contrast,release-vX.Ydoes not change frequently, and any necessary changes will be announced to software users before they are made and/or released as a patch torelease-vX.Y, ensuring stability.
| Branch | Protected? | Created from? | Only merge into? | Status after merging? |
|---|---|---|---|---|
main |
YES | N/A | release-vX.Y |
N/A |
release-vX.Y |
YES | main |
N/A | N/A |
<teamname><featurename> |
NO | main |
main |
Delete after merge |
hotfix-main#<ID> |
NO | main |
main |
Delete after merge |
bugfix-vX.Y#<ID> |
NO | release-vX.Y |
release-vX.Y |
Delete after merge |
This is the unstable release, which represents the latest state of development. That is,
it serves as the single source of truth, meaning it's the definitive and most up-to-date
version of the code for the project. This branch should always be deployable. A pull
request that is reviewed is required to merge code into main.
If the project is open source, contributors without write/permission access to the central repository should fork this branch, which should already be the default branch, and start working from it locally, pushing pull requests to it.
This is the stable release. A pull request that is reviewed is required to merge code
into release-vX.Y. If the branch where code is being merged from is main, then the
commit should be tagged as a release.
If a new feature is assigned to a team, <teamname> should be provided. For instance, if
the team senior-devs is working on a feature named ui-upgrade, they can create their
branch from main and name it as senior-devs/ui-upgrade.
The <teamname> doesn't have to be singular. Multiple sub-teams can exist as long as they
are structured hierarchically. For example, if senior developers delegate work to junior
developers, they can create a branch from senior-devs/ui-upgrade and name it as
junior-devs/senior-devs/ui-upgrade. Once their part of the work is done, the branch should
be merged into senior-devs/ui-upgrade and deleted.
In the same vein, branches such as seniors/junior-devs/senior-devs/ui-upgrade,
juniors/junior-devs/senior-devs/ui-upgrade, and so on, can be created from
junior-devs/senior-devs/ui-upgrade, assuming work is further delegated by junior-devs to
seniors and juniors within the junior-devs team. Each branch should work in a hierarchical
structure from senior-devs/ui-upgrade to the last branch,
juniors/junior-devs/senior-devs/ui-upgrade, to ensure the ui-upgrade feature is
implemented. All branches should be merged into senior-devs/ui-upgrade once all work is
done and then deleted.
If no team is assigned, then there can be no sub-team. Therefore, if a single person is
implementing a feature, <teamname> can be omitted. Optionally, their name can be included,
and a branch named after just the feature, such as john/ui-upgrade or ui-upgrade, can be
created from main and worked on. The <teamname><featurename> branch should be merged
into the main branch once work is completed and deleted afterwards.
This is the branch for any bug fixes against the main branch. In a typical environment,
bugs should be opened as issues within the project using a hosting service
(e.g. Github, Gitlab). To work on the bug, a bug fix branch should be created using the
format: hotfix-main#<ID>, where ID will be the #issue-number generated by your hosting
service (e.g., Github, Gitlab, etc.) when the issue was opened. For example,
hotfix-main#556 is a bug fix for the main branch that fixes the bug found by issue
#556. The hotfix-main#<ID> branch should be merged into the main branch and deleted
afterwards.
This is the branch for any bug fixes against the release-vX.Y branch. In a typical
environment, bugs should be opened as issues within the project using a hosting service
(e.g. Github, Gitlab). To work on that bug, a bug fix branch should be created using the
format bugfix-vX.Y#<ID>, where ID will be the #issue-number generated by your hosting
service (e.g., Github, Gitlab, etc.) when the issue was opened.
For example, bugfix-v1.1#123 is a bug fix for the release-v1.1 branch that fixes the bug
found by issue #123. The bugfix-vX.Y#<ID> branch should be merged into the
release-vX.Y branch and deleted after.
If the bug fixed by the bugfix-v1.1#123 is critical concerning the overall project and
there is a possibility that it still exists in main, a hotfix-main#123 branch should be
created promptly to address and resolve the issue in main as well. When fixing the bug,
it's crucial to bear in mind that changes may have occurred between the release-v1.1 and
main branches, such as changes in dependency versions, platforms, architectures, and so
on. Therefore, it's important to take these changes into account. Once the hotfix-main#123
branch is complete, it should be merged into main and then deleted.
Let contributors know that your project is following the Git+Hub flow by adding the
badge to your README.md:
[](https://github.com/udohjeremiah/Git-Plus-Hub-Flow)