Why GitHub flow
Context and problem statement
Since we develop software in a collaborative setting, we believe it’s important to implement an explicitly stated Git branching strategy. This aligns with our Guiding Principles. A clear and well-defined branching strategy enables consistency and efficiency, and, as a result, cleaner workflows across contributions with more time to focus on actual collaboration, problem-solving, and ensuring high quality work.
There are several branching strategies available, each with its own set of advantages and disadvantages. Which strategy is the most suitable depends on the project, the team, and the organisation (as well as preferences).
The question is, therefore:
Which branching strategy is the best fit for the Seedcase Project?
Decision drivers
With collaborative software development, each developer might have their own way of doing things such as branching, committing, creating pull requests and issues, and reviewing. However, explicitly agreeing on how we do these things will ensure common workflows across developers to help along efficient collaboration.
When a team follows the same workflows, the focus can be shifted from trying to understand what each other are currently working on (how the problem at hand is solved, and why this work is needed) to harnessing each other’s expertise and prior experience and improving the quality of everyone’s work.
For the Seedcase Project, we want to employ a branching strategy that:
- is simple, transparent, and beginner-friendly
- enables consistency across contributions through clear guidelines for branching, committing, and reviewing
- works well with parallel, asynchronous development
- supports continuous delivery
- works well for smaller teams
Considered options
In the following sections, we evaluate commonly used branching strategies to decide on which strategy fits the project and our needs the best. These strategies include: Trunk-based development, Git flow, and GitHub flow.
Note: To keep this decision post relatively short, the strategies and their differences are outlined in a rather simple way, which might result in the loss of some nuances.
Trunk-based development
In trunk-based development, developers frequently integrate their code changes into a shared main
branch, the trunk, instead of working on long-lived additional branches that will be merged into main
less frequently (1). This workflow focuses on making smaller, self-contained changes which helps reduce complexity, minimise conflicts, and enable faster review processes and integration (2). Naturally, this leads to a more continuous integration with frequent merges to the main
branch.
Some smaller teams might even avoid branching altogether and commit directly to the trunk/main
branch.
Benefits
- More continuous integration with frequent merges to the
main
branch - Focuses on smaller, self-contained changes
- Minimises merge conflicts
- Allows for quick releases
- Works well for smaller teams
Drawbacks
- Frequent integration requires strong collaboration and communication skills, potentially with frequent sync-up meetings
- Works best with small, self-contained tasks to enable short-lived branches (or omission of additional branches all together)
Git flow
A contrast to trunk-based development is the Git flow. Git flow is a comprehensive branching strategy with two central branches: main
and develop
. In this strategy, the main
branch always reflect a production ready state of the codebase. In contrast, the develop
branch contains the latest development changes for the next release. When the new developments are at a stable point and is ready to be released, all the changes from the develop
branch will be merged into the main
branch. As a result, whenever there is a new change to the main
branch, this is a new release by definition. Each release version will be tagged (3).
Besides the two central branches, supporting branches will be created to enable parallel development across contributors. These supporting branches are created for specific purposes, such as adding or modifying features (a feature branch) or fixing a critical issue in the code (a hotfix branch). A feature branch must always be created from and merged into the develop
branch, while a hotfix
branch is usually created from the main
branch and is be merged into both main
and develop
.
Benefits
- Clear framework offering an explicit shared understanding of the branching and releasing processes
- Clear responsibilities for each branch
- Versioning per definition
- Production versions are easy to navigate through tags
Drawbacks
- Revolves around releases, and we, currently, need a more continuous delivery-like approach
- Complexity due to the number of branches, which could lead to merge conflicts and slow down the development process
GitHub flow
GitHub flow is a simpler branching strategy than Git flow, revolving around the main
branch. The only “hard” rule in this workflow is that anything on the main
branch is deployable (4). Whenever new work needs to be done, a new branch with a descriptive name is created from the main
branch. Like with the Git flow, types of branches include (among others) feature
and hotfix
branches. After a new branch has been created, changes are made on this branch with regular pushes and descriptive commit messages.
When the developer wants feedback, they create a pull request, which their collaborators review. Any suggested changes are addressed and implemented. When the work is complete, the branch can be merged into the main
branch and is deleted. With this branching strategy, the work on the new branch is deployed as soon as it is merged into main
.
Benefits
- Allows for continuous development and the ability to quickly address issues of all kinds (including security issues, bugs, and small feature requests)
- The same simple processes are used to address smaller and larger developments
- Works well for smaller teams and asynchronous collaboration, common in open-source projects
Drawbacks
- Does not by definition include releases
- Might be more susceptible to bugs in production (compared to Git flow) because of the lack of dedicated development branches
- Long-living branches can increase the risk of merge conflicts
Decision outcome
We decided on using the GitHib flow branching strategy because:
- It is simple and beginner-friendly strategy
- It is both well-known and well documented, creating clear guidelines that enable consistency across contributions
- It offers clear guidelines on every step of collaborative development, including branching, committing, and review processes
- Longer-living branches works well with parallel, asynchronous work
- The balance between having multiple branches as well as using continuous integration and delivery approaches
- Not overly complex for a smaller team like ours
- Allows for continuous development with the same simple processes for both
Consequences
Even though the GitHub flow is the most suitable branching strategy for the Seedcase Project right now, this choice does come with consequences. For example, working on longer-living branches (compared to trunk-based-development) could increase the risk of merge conflicts (which is easier to avoid using trunk-based-development). This strategy also comes without release tagging (as Git flow does), something we might want to implement for Seedcase software products later on.
However, GitHub flow eases the process of parallel, asynchronous development and is ideal for smaller teams like ours. While we deploy continuously, a relatively simple workflow like GitHub flow is the best fit for us.