Gitflow: 7 Steps to Branch, Release, and Hotfix

- Release tag
- Feature flag
- Loglune
Gitflow is the branching model Vincent Driessen published in January 2010: two long-lived branches, master for production-ready code and develop for the next release, plus feature, release, and hotfix branches with fixed rules for where each one starts and where it merges back. This guide uses Gitflow in 7 steps: check that your software fits Gitflow, set up the main branches, develop on feature branches, cut a release branch, finish the release, fix production with hotfix branches, and ship merged but unreleased features switched off with feature flags.
The steps follow Driessen’s post and apply to software released in explicit versions. They are for teams that ship versioned releases and want fixed rules for branches, releases, and hotfixes. The final step adds feature flags, which Driessen’s post does not cover.
What Gitflow means
Driessen’s post A successful Git branching model (January 5, 2010) presents Gitflow as a set of procedures that every team member follows to reach a managed software development process. The repository setup has one central repository, called origin, that the team treats as the source of truth, and each developer pulls from and pushes to it. Driessen’s note of reflection spells the branching model git-flow; this guide writes Gitflow.
Driessen calls master and develop the main branches, with an infinite lifetime, and calls feature, release, and hotfix branches supporting branches, with a limited lifetime because they are removed eventually. Driessen’s post also says the supporting branches are plain Git branches, categorized by how the team uses them. Gitflow is therefore a branching strategy with release management rules: Driessen’s post says it covers the branching strategy and release management of the author’s projects.
| Branch | Branches off from | Merges back into | Naming | Lifetime |
|---|---|---|---|---|
| master | Not specified | Not specified | master | Unlimited; every merge into it is a production release |
| develop | Not specified | Not specified | develop | Unlimited; the integration branch for the next release |
| Feature | develop | develop | Any name except master, develop, release-, or hotfix- | Until the feature is merged or discarded |
| Release | develop | develop and master | release-* | Until the release is tagged and merged back |
| Hotfix | The tag of the production version on master | master and develop, or the open release branch instead of develop | hotfix-* | Until the fix is tagged and merged back |
Before you adopt Gitflow
Six inputs decide whether the branch rules hold up in daily work.
- A central repository that the team treats as origin.
- A version numbering rule, because Gitflow assigns the version number when a release branch starts.
- A build that runs from develop, such as the automatic nightly build in Driessen’s post.
- A decision on who finishes releases and hotfixes, since those steps merge into master and create tags.
- A feature flag setup for features that merge before they are ready for customers.
- A record of which release each customer runs, when several versions are supported at once.
How to use Gitflow in 7 steps
1. Check that your software fits Gitflow
Driessen’s note of reflection (March 5, 2020) says Gitflow became hugely popular and that many teams started treating it as a standard, and also as a dogma or panacea. Driessen’s 2020 note says web apps are typically delivered continuously, not rolled back, and do not need several versions supported in the wild, and that continuously delivered web apps are not the class of software Gitflow was written for.
| Your software | Driessen’s 2020 suggestion |
|---|---|
| A web app delivered continuously, with one version in production | A much simpler workflow, such as GitHub flow |
| Explicitly versioned releases | Gitflow may still fit |
| Several versions supported in the wild | Gitflow may still fit |
Driessen’s 2020 note ends by telling teams to consider their own context and decide for themselves.
2. Set up master and develop
Driessen’s model keeps two main branches in the central repository. The HEAD of master always reflects a production-ready state, and the HEAD of develop reflects the latest delivered development changes for the next release. Driessen notes that some call develop the integration branch and that automatic nightly builds come from it.
Every merge into master is a new production release by definition. Driessen’s team was strict enough about this rule that a script could, in principle, build and roll out the software to production on every commit to master.
3. Develop each feature on a feature branch
Start each feature on a branch off develop, and merge it back into develop when it is finished, or discard it after a disappointing experiment. Driessen notes that feature branches typically live in developer repositories and not in origin, and that the target release of a feature may be unknown when work starts.
Driessen merges feature branches with the –no-ff flag, which always creates a merge commit even when a fast-forward is possible. The merge commit keeps the record that the feature branch existed, groups the commits that added the feature, and makes reverting the whole feature straightforward.
4. Cut a release branch when develop is almost ready
Branch a release branch off develop when develop almost reflects the desired state of the new release. Every feature targeted at that release must be merged into develop by then, and features for later releases wait until the release branch exists. Driessen assigns the version number at the start of the release branch and not earlier.
While the release branch is open, it takes minor bug fixes and release metadata such as the version number and build dates. Driessen strictly prohibits large new features on a release branch; they go to develop and wait for the next release. Meanwhile develop is free to receive features for the next release.
5. Finish the release: merge, tag, and merge back
When the release branch is ready, merge it into master and tag that commit on master for future reference. Then merge the release branch back into develop, so later releases keep its bug fixes. Driessen expects the merge back into develop to conflict, likely over the version number, and the conflict is fixed and committed. After both merges, the release branch is removed. Driessen also mentions signing the tag cryptographically as an option.
6. Fix production with a hotfix branch
When a critical bug in production must be fixed at once, branch a hotfix branch off the tag on master that marks the production version, bump the version number, and commit the fix. Work on develop continues while one person prepares the fix.
To finish, merge the hotfix into master and tag it, then merge it into develop. When a release branch exists at that moment, merge the hotfix into the release branch instead, and the fix reaches develop when the release finishes; if develop needs the fix at once, Driessen says it can be merged into develop as well. When the failing code path sits behind a feature flag, switching the flag off stops the problem for customers while the hotfix branch is prepared, and the fix still goes through master and develop.
7. Ship merged but unreleased features switched off with feature flags
In Gitflow, a feature merged into develop joins the next release, and a feature meant for a later release waits on its branch until the current release branch is cut. A feature flag adds another option: merge the feature into develop with its code path switched off, ship it in the release, and switch it on later without a new release. Pete Hodgson’s article Feature Toggles (October 9, 2017) describes release toggles, which let incomplete code paths ship to production as latent code that may never be turned on.
In Loglune, switching the feature on after the release is a flag edit, and every flag edit is appended to the change history as a change event with the customer, the actor, the time, the target flag, and the values before and after. Loglune evaluates flags on its server and assigns percentage buckets with MurmurHash3 hashing, so a customer lands in the same bucket for the same rule whichever release sends the request. When a customer reports a problem after the release, pick the customer and the time T of the report. Loglune rebuilds the flag state at T from the change history and delivers it in reproduction mode to a development, CI, or staging environment, and one delivery counts as one reproduction. Read together with the release tag the customer runs, the rebuilt flag state shows which code path the customer was on. Loglune reproduces the flag evaluation, not the root cause in application code. The walkthrough on reproducing a bug that affects one customer covers the path from a report to a reproduction.
Loglune’s example dataset follows one release toggle from creation to removal readiness. The dataset is synthetic input labeled Example data in the Loglune console at loglune.com/app, visible without signing in, and it describes no customer and no real incident. In the example dataset, the boolean flag checkout-v2 was created with the default variation off on August 1, 2026, at 09:00 UTC (version 1, labeled “initial rollout”); the rule r-beta, which serves on to the segment beta-users, was added on August 8, 2026, at 14:30 UTC (version 2, labeled “beta targeting”); and the default variation of checkout-v2 was switched from off to on for general availability on August 20, 2026, at 11:15 UTC (version 3). Each of the three changes is a flag edit, with no release branch and no new tag. Comparing version 2 with version 3 in the console’s Rollout guard returns one finding, a defaultFlip of checkout-v2 from off to on with severity high. Flag readiness for checkout-v2 at version 3, evaluated on September 29, 2026, returns the verdict ok with the reason “quiet for 39 days; serves on to everyone”, so the flag check in the code is ready to be deleted on the next feature branch off develop.
Editorial example (not a customer case): a feature merged and switched off across a release
The table follows one feature through a Gitflow release of a desktop invoicing app. Weeks, versions, and names are illustrative.
| When | Branch or tag | Event | bulk-export flag |
|---|---|---|---|
| Week 1 | feature/bulk-export | Feature developed on a branch off develop | Created, off for every customer |
| Week 2 | develop | Feature merged, launch date not set | Off |
| Week 3 | release-2.4 | Release branch cut, version 2.4 assigned | Off |
| Week 4 | master, tag 2.4 | Release merged into master and tagged, then merged back into develop | Off |
| Week 5 | No new release | Export switched on for 3 pilot customers | On for 3 customers, change event recorded |
| Week 6 | No new release | A pilot customer reports a failed export from Tuesday at 4:05 p.m. | Customer’s flag state at that time rebuilt in staging, showing the export on |
| Week 6 | hotfix-2.4.1 | Fix branched off tag 2.4, merged into master and develop, tagged 2.4.1 | On for 3 customers |
The rebuilt flag state and the customer’s release, 2.4, pointed the team to the export code path in tag 2.4, so the hotfix branched off tag 2.4 instead of starting from develop.
Troubleshooting Gitflow
- The history no longer shows which commits formed a feature: merge feature branches with –no-ff, as Driessen recommends, so each feature has its own merge commit.
- The merge of a release branch back into develop conflicts: expect a conflict over the version number, fix it, and commit, as Driessen’s post describes.
- A large feature lands on a release branch: move it to develop, because Driessen’s model prohibits large new features on a release branch.
- A hotfix is missing from the next release: merge the hotfix into develop as well as master, or into the open release branch when one exists.
- The team delivers a web app continuously and Gitflow slows it down: consider the much simpler workflow Driessen suggests in the 2020 note.
- A customer report arrives after a feature was switched on without a release: rebuild that customer’s flag state at the reported time, and read it with the release tag the customer runs.
FAQ
What are the downsides of Gitflow?
The downsides of Gitflow are the waiting and the merge work its branch rules add, and Driessen’s 2020 note suggests a much simpler workflow for continuously delivered web apps, which are not the class of software Gitflow was written for. Within Driessen’s own rules, a feature for a later release waits until the current release branch is cut, the merge of a release branch back into develop is expected to conflict over the version number, and a hotfix has to be merged into both master and develop, or into the open release branch, or the fix goes missing from the next release.
What is the difference between Gitflow and GitHub flow?
Gitflow keeps two long-lived branches, master and develop, plus release and hotfix branches, while GitHub flow works from one default branch with short-lived branches merged through pull requests. The GitHub Docs page GitHub flow (checked September 29, 2026) calls GitHub flow a lightweight, branch-based workflow with six steps: create a branch, make changes, create a pull request, address review comments, merge the pull request so the changes appear on the default branch, and delete the branch. The GitHub Docs page names no develop, release, or hotfix branch, and Driessen’s 2020 note gives GitHub flow as the example of a much simpler workflow for continuously delivered web apps.
Do you need the git-flow command-line tool to use Gitflow?
No, Gitflow works with plain Git commands, because Driessen’s post says the supporting branches are plain Git branches categorized by how the team uses them. The nvie/gitflow README describes git-flow as a collection of Git extensions for Driessen’s branching model: git flow init sets up the branch structure, and git flow feature, git flow release, and git flow hotfix start and finish each branch type. The same README (checked September 29, 2026) says the original command-line extension is no longer maintained and points new users to git-flow-next by Tower, which the README describes as backward compatible with git-flow and actively maintained.
Deciding whether the Gitflow branching strategy fits
Use Gitflow when the software ships in explicit versions or several versions must be supported in the wild, and the team wants release branches for stabilizing each version. Choose a simpler workflow for a continuously delivered web app, as Driessen’s 2020 note suggests. In either model, put features that merge before launch behind feature flags and keep the flag change history, so a report after a release can be traced to both the release tag and the flag state one customer had at that moment.
Check what a Gitflow release served one customer
In a Gitflow project, a release tag fixes the code, and feature flags decide which code paths run after the release. Loglune records every flag edit as a change event with the actor, the time, and the values before and after, and rebuilds the flag state a customer had at time T for your development, CI, or staging environment. The Free plan includes 5 reproductions.