git
workflow
project-management

Presented approach is used in 4markdown.com repository. You can check the branches, how they're merged, and what kind of CI/CD checks are performed. In addition, you can investigate how issues from the project are handled via linear git history.

GitFlow Tutorial

Git workflow is an extremely important part of every project. If it's designed or implemented badly, it will cause a lot of headaches, frustration, and wasted time. Let's explore the GitFlow concept and dive through the strong and weak sides of this approach.

What is GitFlow?

It's a branching model that is strongly focused on having two primary branches: develop and main.

Core Branches in GitFlow The Most Important Branches in GitFlow

The main branch is production. It contains accepted code/features that your users will use. In this approach, the main is reserved only for reflecting production-ready code. You cannot directly push to this branch.

The develop branch holds all features from the main and "new" ones. So, you can think about it like a develop branch is one version ahead main branch. Take a look at the following commit list to understand:

// develop commits
bug(app): links wrap issue
chore(app): add ci/cd
feat(app): add theme support
feat(app): add authorization
// main commits
feat(app): add theme support
feat(app): add authorization

So, develop has two more commits when compared with main. Let's say we want to go to production (merge the code from develop to main). We cannot do that directly. We need a pull request. But it cannot be just develop -> main. GitFlow approach requires from us to create a release branch. This one is a special type of branch. It should be always created from develop and tagged correctly.

Release Branches Only Release Branches Creation and Merging

As you saw we started from the develop branch and merged the release branches to the main. It's good to point out the special names of these. Each must have a unique name, incremented by a specific version of the software.

The convention of naming release branches is up to you. Usually, it follows Semver convention.

Ok, to this moment all should be simple. You cannot push directly to the main, firstly you need to create a release branch from develop, raise PR, and merge this release branch to the main. What about the develop branch itself? So, you cannot merge to develop directly either. You need the next type of branch - feature branch. This one must be always created from develop and merged to develop later.

Feature and Release Branches Feature Branches and Release Branches Together

There is one more branch type - hotfix. It has an important role. So, what if there is an ugly bug spotted out on production (code located on the main branch)? If you would like to follow the flow presented to this moment, you'll need to push a fix to develop, create a release branch, and merge it to the main. However, this approach is risky. What if develop already contains other features? That's why hotfix branches have been provided. They're reducing the code freeze risk.

The hotfix branch must be always created from main, merged to main, and then merged to develop.

Hotfix showcase Showcase of Hotfix Branch

The flow now seems to be a little bit more complicated. That's why below you've fancy gif to repeat the process.

GitFlow Process Showcase Full GitFlow Process

How to Merge in GitFlow

In GitFlow you'll merge a lot, so you need to know how to do that. The first topic is to merge feature branch to develop. Here the algorithm is simple - just squash and merge your PR as a single commit. Then each feature merged to develop will have a dedicated commit.

What about merging the release branch to the main? Here you'll need a rebase. It's because you want to have linear Git history without merging commits. So, this is an example of such history:

Linear Git History Linear and Descriptive Git History

CI&CD for GitFlow

GitFlow is kinda complex, so proper automation and checks, may be healthy for development performance. It's really important to have a proper setup, that removes from you additional, manual work.

For Develop

When raising a pull request to the develop branch from the feature branch, the following checks are required:

  1. Automatic deployment for the ephemeral environment. The one created when PR is raised, and closed when PR is merged.
  2. Tests (partial or full e2e tests/unit/integration).
  3. Linting/Code quality checks.

For Main

When raising a pull request to the main branch from the release branch, the following checks are required:

  1. Automatic deployment for the environment that mitigates production. In this environment, you'll perform regression testing/full test cycle before going to prod.
  2. Full e2e tests.

Strong Sides of GitFlow

  1. Structured Workflow: Provides a clear, predictable branching structure that is ideal for larger teams.
  2. Feature Development Isolation: Enables developers to work on features independently without affecting the main codebase.
  3. Support for Concurrent Releases: Facilitates the management of multiple versions of an application simultaneously.
  4. Clear Role of Each Branch: Each branch type has a specific role, enhancing clarity and ease of onboarding for new developers.
  5. Stable Main Branch: Keeps the main branch free from development changes, ensuring it is always ready for production.
  6. Simplified Hotfixes: Allows for quick fixes to production issues with minimal disruption.
  7. Enhanced Release Management: Supports systematic preparation and deployment of new releases.

Consequences of using GitFlow

  1. Complexity: It can be overly complex for smaller projects, introducing unnecessary overhead.
  2. Steep Learning Curve: The model can be difficult for newcomers, potentially slowing initial productivity.
  3. Frequent Merges and Conflicts: More branching and merging increase the likelihood of conflicts, requiring careful management.
  4. Slow Feature Integration: Features are merged into main branches in stages, which can delay their deployment.
  5. Rigid Structure: The fixed workflow may limit the flexibility needed for some project requirements.
  6. Maintenance Overhead: Managing multiple branch types demands ongoing attention and upkeep.
  7. Higher Cost: CI/CD is much more expensive when compared to alternatives.
  8. Mistakes Hurts: If you merge something in an invalid way, there may be a lot of required work to fix it.

GitFlow might not be ideal for smaller or agile projects due to its intricate and maintenance-heavy nature.

Alternatives

Several popular alternatives to Gitflow might be better suited for different team sizes, project requirements, or development methodologies. Here are a few commonly used Git branching models:

  1. GitHub Flow: Simple model ideal for projects with frequent deployments. Involves a main branch and short-lived feature branches that are merged and deployed quickly.
  2. GitLab Flow: Similar to GitHub Flow but includes environment branches for staging and production, integrating well with continuous integration and deployment processes.
  3. Trunk-Based Development: Developers work on a single main branch with minimal use of short-lived feature branches, emphasizing rapid integration and continuous delivery.
  4. Feature Toggle Flow: Manages features using toggles within the main codebase, allowing features to be tested in production without full deployment.
  5. OneFlow: Combines elements of GitFlow and GitHub Flow with a main development branch, feature branches, and more flexible release branches.

Each model varies in complexity and deployment frequency suitability, providing different benefits depending on your project's needs and team structure.

Summary

Overall, while GitFlow can be very effective for managing complex releases and large teams, its complexity and maintenance requirements may not be suitable for every project, particularly those that are smaller or require a more flexible and faster-paced development cycle. Remember, using GitFlow takes time due to complexity, but it provides a nice decoupled workflow that allows you to release stuff in a stable and scalable way.