The Gitflow Development Workflow

12 min read·Jan 1, 2025

Gitflow is a popular Git branching workflow designed to facilitate collaboration by streamlining the development process of software releases.

It involves the use of both permanent and temporary branches, and dictates how branches should be set up and merged.

It is generally used for projects with a scheduled release cycle and for the DevOps best practice of continuous delivery.

The main and develop branches

Gitflow uses two permanent branches:

  • The main branch, used for integrating official tagged releases.
  • The develop branch, derived from the main branch, used for integrating the work done on temporary feature branches.

The main difference between these two branches resides in the fact that the develop branch will contain the full history of the project, meaning all of the development commits, whereas the main branch will only contain a condensed version of it.

💡 Tip: The objective is to keep the main and develop branches as in sync as possible throughout the whole development lifecycle.

Workflow overview

Step 1: Initializing and connecting the repository

The first step consist in initializing the project's repository using the git init command:

$ git init

And connect it to a remote repository using the git remote command:

(main)$ git remote add origin git@github.com:<username>/<repository>.git

Step 2: Creating the develop branch

By default, Git only creates the main branch upon initialization.

Consequently, you have to manually create the develop branch using the git branch command:

(main)$ git branch develop

Step 3: Synchronizing repositories

Once the main and develop branches created, you need to synchronize the local repository with the remote repository by uploading both branches using the git push command:

(main)$ git push -u origin main
(main)$ git push -u origin develop

The feature branches

Feature branches are temporary branches that contain a full feature.

Instead of being forked from the main branch they are derived from the develop branch in which they will be merged back into when the feature is considered done and tested.

That way, they never interact with the main branch directly so they can never corrupt the production-ready code.

Feature branches are usually prefixed with the feature keyword, followed by a short description of the feature:

feature/<description>

For example:

feature/user-token-authentication
feature/video-streaming-endpoint

Workflow overview

Step 1: Creating a feature branch

Before creating a feature branch, you need to first switch from the main branch to the develop branch:

(main)$ git switch develop

Then pull the latest commits other developers may have added:

(develop)$ git pull

Once the develop branch is in sync with the remote repository, you can create the feature branch and switch to it to start the development of the feature:

(feature/new-feature)$ git switch -c feature/new-feature

Step 2: Merging the feature branch into the develop branch

Once the feature branch is considered ready, you can switch back to the develop branch:

(feature/new-feature)$ git switch develop

Merge the feature branch into it:

(develop)$ git merge --no-ff feature/new-feature

And push its commits to the repository:

(develop)$ git push

Step 3: Deleting the feature branch

Once the feature branch has been merged into the develop branch, you can delete it both locally and remotely:

(develop)$ git branch -d feature
(develop)$ git push origin --delete feature

The release branches

When the develop branch has acquired enough features for a release or a feature is ready to be deployed, a new branch is forked from it called a release branch.

At this point the release branch cannot be modified anymore, therefore preventing any last minute changes that were not planned.

The only allowed changes at this point are eventual bug fixes and documentation updates.

Using release branches also allows for one team to eventually polish the current release while another team keeps working on features for the next release cycle.

The release branch then gets merged back into the main branch and a tag is created accordingly.

Release branches are usually prefixed with the release keyword, followed by a version number:

release/v<version>

For example:

release/v2.0.1

Workflow overview

Step 1: Creating a release branch

Once the develop branch has accumulated enough features, you can create a new release branch from it:

(develop)$ git switch -c release/v1.2.3

Make any necessary changes to finalize the release, such as fixing minor bugs or updating documentation, and commit the changes to the repository:

(release/v1.2.3)$ git push

Step 2: Merging the release branch into the develop branch

To keep the develop branch in sync with the latest release, you need to switch to the develop branch and merge the release branch into it:

(release/v1.2.3)$ git switch develop
(develop)$ git merge --no-ff release/v1.2.3
(develop)$ git push

Step 3: Merging the release branch into the main branch

Once you've synchronized the develop branch, you need to do the same thing with the main branch:

(develop)$ git switch main
(main)$ git merge --no-ff release/v1.2.3

Once merged, you can create a new tag for the latest commit of the main branch using the git tag command:

(main)$ git tag -a v1.2.3 -m "rc-1.2.3"

And push this tag to the repository:

(main)$ git push --tags

Step 4: Deleting the release branch

Finally, once the release branch has been merged and tagged, you can delete it both locally and remotely:

(main)$ git branch -d release/v1.2.3
(main)$ git push origin --delete release/v1.2.3

The hotfix branches

Hotfix branches are temporary branches that contain critical production patches.

They are directly forked from the main branch.

Once the fix is ready, it is merged back in both the main and the develop branch, creating thereby a new release tag on the main branch.

Hotfix branches are usually prefixed with the hotfix keyword, followed by a short description:

hotfix/<description>

For example:

hotfix/fix-password-encryption

Workflow overview

Step 1: Creating a hotfix branch

The first step consists in creating a hotfix branch derived from the main branch:

(main)$ git pull
(main)$ git switch -c hotfix

Then pushed to the repository when ready:

(hotfix)$ git push

Step 2: Merging the hotfix branch into the main branch

Once the hotfix is ready, it can be merged back into the main branch:

(hotfix)$ git checkout main
(main)$ git merge --no-ff hotfix
(main)$ git push

And tagged to reflect a version change of the application:

(main)$ git tag -a <version> m <message>
(main)$ git push --tags

Step 3: Merging the hotfix branch into the develop branch

Once merged into the main branch, it should also be merged into the develop branch to keep both lines of development in sync:

(main)$ git checkout develop
(develop)$ git pull
(develop)$ git merge --no-ff hotfix
(develop)$ git push

Step 4: Deleting the hotfix branch

Once the hotfix fully integrated, the hotfix branch can be deleted both locally and remotely:

(develop)$ git branch -d hotfix
(develop)$ git push origin --delete hotfix

Summary

Here's a summary of what you've learned in this lesson:

  • The main branch holds the production-ready code and only contains stable releases.
  • The develop branch serves as the integration branch for features and prepares the next release.
  • The feature branches are used for developing new features or improvements. They are branched off the develop branch.
  • The release branches are used for preparing new production releases by finalizing the version. They are branched off the develop branch.
  • The hotfix branches are used for quickly fixing critical issues in production. They are branched off the main branch.

Enjoying the courses?

I've made these courses completely free so anyone can learn from them. If they've helped you and you'd like to actively support the work behind BackendBrewery, you can leave a tip:

Support BackendBrewery
The Gitflow Development Workflow | Backend Brewery