Lesson 113 of 12115 min read

GitLab Flow: Environment Branches (Production, Pre-Production)

Learn GitLab Flow, which adds environment-specific branches on top of a GitHub Flow-like base, explicitly mapping branches to deployment stages.

Author: CodersNexus

GitLab Flow: Environment Branches (Production, Pre-Production)

GitHub Flow's simplicity comes with a real gap: it doesn't explicitly address deployments that pass through multiple distinct stages — a staging or pre-production environment before actually reaching production, for instance. GitLab Flow addresses exactly this gap, adding a small number of additional, explicitly named branches on top of a GitHub Flow-like foundation, each corresponding directly to a specific deployment environment.

Learning Objectives

  • Explain the specific gap in GitHub Flow that GitLab Flow addresses.
  • Understand how environment branches map directly to deployment stages.
  • Trace how a change flows through multiple environment branches toward production.
  • Recognize GitLab Flow as an intermediate point between GitHub Flow's simplicity and Git Flow's structure.

Key Terms to Know Before Learning GitLab Flow

  • GitLab Flow: A branching strategy building on GitHub Flow's simple main-branch foundation, adding explicit environment branches corresponding to deployment stages.
  • Environment branch: A long-running branch (such as pre-production or production) representing the code currently deployed to that specific environment.
  • Upstream first: GitLab Flow's principle that changes should always be merged into main first, then flow downstream toward environment branches, never the reverse.

How the GitLab Flow Branching Model Actually Works

GitHub Flow's single rule — `main` is always deployable — implicitly assumes a fairly direct path from `main` to production. But many real teams have a **multi-stage deployment pipeline**: code might need to pass through a staging or pre-production environment for final validation before actually reaching production, and the team wants their branch structure to explicitly reflect and track this reality, rather than relying purely on external tooling to manage the distinction.

**GitLab Flow** addresses this by keeping GitHub Flow's simple foundation — a `main` branch, short-lived feature branches, pull/merge requests — but adding one or more additional, long-running **environment branches**, each named after and corresponding directly to an actual deployment stage:

```
main → pre-production → production
```

Each environment branch represents **exactly what's currently deployed to that specific environment**. When a feature branch is merged, it merges into `main` first (following GitHub Flow's normal process) — and then, separately, changes flow **downstream** from `main` toward `pre-production`, and finally from `pre-production` toward `production`, typically once each stage's validation (automated tests, manual QA, a staged rollout) has passed.

This embodies GitLab Flow's key principle, often called **'upstream first'**: changes should always be merged into `main` first, and then flow downstream toward environment branches — never the reverse, and never directly into a downstream environment branch, skipping `main`. This keeps `main` as the consistent, single source of truth for all actual development work, with the environment branches serving purely as **deployment state trackers**, showing exactly what code is live in each specific environment at any given moment — genuinely useful for teams wanting to answer 'what's currently in staging versus production?' by simply looking at Git history, rather than needing to check a separate deployment dashboard or tool.

GitLab Flow can be seen as occupying a middle ground between the two strategies covered in the previous two lessons: it retains GitHub Flow's simplicity for actual day-to-day feature development (one main branch, short-lived feature branches, pull requests), while adding just enough additional structure — environment branches — to explicitly model a multi-stage deployment pipeline, without going as far as Git Flow's full five-branch-type model with its separate `develop` branch and formal release/hotfix distinction. It's worth noting GitLab Flow also has a variant specifically for teams with formally versioned releases (release branches, similar in spirit to Git Flow's `release/*`), but the environment-branch variant covered here is its most distinctive, commonly discussed contribution.

GitLab Flow Environment Branches: Visual Walkthrough

Draw three sequential long horizontal branch lines, stacked vertically: 'main' (top), 'pre-production' (middle), 'production' (bottom). Show a feature branch merging INTO main via a pull request. Draw a downstream arrow from main to pre-production labeled 'merge once ready for staging validation'. Draw another downstream arrow from pre-production to production labeled 'merge once staging validation passes'. Add a large 'UPSTREAM FIRST' label with an arrow pointing strictly left-to-right/top-to-bottom, captioned 'Changes NEVER skip main or flow backward — always main → pre-production → production, in that order.'

GitLab Flow vs GitHub Flow: Key Differences

AspectGitHub FlowGitLab Flow
Long-running branchesOne: main onlymain PLUS one or more environment branches (e.g., pre-production, production)
Represents deployment stages explicitly?No — external tooling tracks thisYes — each environment branch tracks exactly what's deployed there
Merge directionFeature branches → mainFeature branches → main → environment branches, in that order ('upstream first')
Best fitSimple, single-stage deployment (deploy straight from main)Multi-stage deployment pipelines (staging before production)

GitLab Flow: Command Syntax and Examples

# Feature work follows GitHub Flow's normal process, merging into main first
git switch main
git switch -c feature/add-checkout-discount
# ... work, PR, review, merge into main ...

# Once ready to promote to the pre-production environment,
# merge main INTO pre-production (downstream, never the reverse)
git switch pre-production
git merge main
git push
# (this typically triggers an actual deployment TO the pre-production environment)

# Once pre-production validation passes, promote further downstream to production
git switch production
git merge pre-production
git push
# (this triggers an actual deployment TO production)

# 'Upstream first' rule in practice: NEVER do this —
# git switch pre-production
# git merge feature/add-checkout-discount   # WRONG — skips main entirely

Breaking Down the GitLab Flow Example

The feature branch portion of this example is identical to GitHub Flow — branch from `main`, work, open a PR, merge back into `main`. What's new is the explicit downstream promotion: merging `main` into `pre-production` (typically triggering an actual deployment to that environment), and later merging `pre-production` into `production` (triggering the actual production deployment), each merge corresponding directly to an actual deployment event. The final commented-out block demonstrates exactly what GitLab Flow's 'upstream first' principle forbids — merging a feature branch directly into a downstream environment branch, skipping `main` entirely, which would break `main`'s role as the single, consistent source of truth for all development work.

How GitLab Flow Is Used on Real Engineering Teams

  • GitLab (the platform this strategy is named after) documents and recommends this exact model extensively in its own official workflow documentation, directly reflecting how many of its own teams and users structure their deployment pipelines.
  • Teams with a genuine, multi-stage deployment process (development, staging, production) commonly adopt some variant of environment branches specifically to make their deployment state visible and trackable directly through Git history, rather than relying solely on external deployment dashboards.
  • Some teams implement environment branches with corresponding branch protection rules (Module 4) restricting who can merge into production specifically, using GitLab Flow's structure as a natural point to layer additional access control on top of.
  • CI/CD systems (the focus of a later lesson this module) commonly trigger different deployment pipelines based on which environment branch just received a push, making GitLab Flow's branch structure a direct, natural input into automated deployment tooling.

GitLab Flow Interview Questions and Answers

Q1. What specific gap in GitHub Flow does GitLab Flow address?

GitHub Flow assumes a fairly direct path from main to production, without explicitly modeling multi-stage deployment pipelines. GitLab Flow addresses this by adding environment branches (like pre-production and production), each explicitly representing what's currently deployed to that specific stage, directly trackable through Git history.

Q2. What is GitLab Flow's 'upstream first' principle?

Changes should always be merged into main first, and then flow downstream toward environment branches in order — never merged directly into a downstream environment branch, skipping main. This keeps main as the single, consistent source of truth for all development work, with environment branches serving purely as deployment state trackers.

Q3. How does GitLab Flow compare structurally to Git Flow and GitHub Flow?

It occupies a middle ground: it retains GitHub Flow's simplicity for day-to-day feature development (one main branch, short-lived feature branches, pull requests), while adding environment branches on top specifically to explicitly model a multi-stage deployment pipeline, without going as far as Git Flow's full five-branch-type structure with a separate develop branch.

GitLab Flow Quiz: Test Your Understanding

1. What gap in GitHub Flow does GitLab Flow specifically address?

  1. The lack of pull requests
  2. The lack of explicit branches modeling a multi-stage deployment pipeline
  3. The inability to create feature branches
  4. The absence of a main branch

Answer: B. The lack of explicit branches modeling a multi-stage deployment pipeline

Explanation: GitHub Flow's single main branch doesn't explicitly model deployment stages like staging versus production; GitLab Flow adds environment branches specifically for this purpose.

2. What does GitLab Flow's 'upstream first' principle require?

  1. Changes must always be merged into main first, then flow downstream toward environment branches
  2. Environment branches must be merged into main first
  3. All commits must be made directly to production
  4. Feature branches must skip main entirely

Answer: A. Changes must always be merged into main first, then flow downstream toward environment branches

Explanation: This principle ensures main remains the single, consistent source of truth for all development work, with changes always flowing in one direction — from main toward environment branches, never the reverse.

3. What does an environment branch like 'production' represent in GitLab Flow?

  1. A branch for experimental, unstable features
  2. Exactly what's currently deployed to that specific environment
  3. A backup of the entire repository
  4. A branch reserved only for documentation changes

Answer: B. Exactly what's currently deployed to that specific environment

Explanation: Environment branches serve as deployment state trackers, with each one's content corresponding directly to what's actually currently live in that specific deployment environment.

Common Mistakes When Using GitLab Flow

  • Merging a feature branch directly into a downstream environment branch, skipping main entirely and violating the 'upstream first' principle.
  • Assuming GitLab Flow requires the same five-branch-type complexity as Git Flow, when it actually retains GitHub Flow's simplicity for day-to-day feature work.
  • Not keeping environment branches genuinely in sync with what's actually deployed, undermining their core purpose as accurate deployment state trackers.
  • Adopting environment branches when a team's deployment process is actually simple and single-stage, adding unnecessary structure that GitHub Flow alone would have handled fine.

GitLab Flow: Exam-Ready Quick Notes

  • GitLab Flow: GitHub Flow's simple foundation (main + feature branches + PRs) + environment branches for deployment stages.
  • Environment branches (e.g., pre-production, production): each represents exactly what's currently deployed to that stage.
  • 'Upstream first': changes merge into main FIRST, then flow downstream toward environment branches — never skip main or flow backward.
  • GitLab Flow occupies a middle ground between GitHub Flow's simplicity and Git Flow's full structure.

GitLab Flow: Key Takeaways

  • GitLab Flow adds environment branches on top of GitHub Flow's simple foundation, specifically to explicitly model a multi-stage deployment pipeline.
  • The 'upstream first' principle keeps main as the single, consistent source of truth, with changes always flowing downstream from it toward environment branches, never the reverse.
  • GitLab Flow represents a middle ground between GitHub Flow's simplicity and Git Flow's more extensive five-branch-type structure.

Frequently Asked Questions About GitLab Flow

Q1. What is GitLab Flow?

It's a branching strategy that builds on GitHub Flow's simple main-branch foundation, adding environment branches (like pre-production and production) that explicitly represent and track a team's multi-stage deployment pipeline.

Q2. What problem does GitLab Flow solve that GitHub Flow doesn't address?

GitHub Flow assumes a fairly direct path from main to production, without explicitly modeling intermediate deployment stages like staging. GitLab Flow adds environment branches specifically to make these stages visible and trackable directly through Git history.

Q3. What does 'upstream first' mean in GitLab Flow?

It means changes must always be merged into main first, and then flow downstream toward environment branches in order — never merged directly into a downstream environment branch while skipping main, keeping main the single, consistent source of truth.

Q4. How does GitLab Flow compare to Git Flow?

GitLab Flow is generally simpler than Git Flow — it doesn't have a separate develop branch or formal release/hotfix branch types. It adds environment branches on top of a GitHub Flow-like base specifically for tracking deployment stages, without Git Flow's fuller five-branch-type structure.

Q5. Do I need GitLab Flow if my team deploys directly from main with no intermediate stages?

Probably not — if your deployment process is simple and single-stage, GitHub Flow alone likely serves you well without the added complexity of environment branches, which are specifically valuable when a genuine multi-stage deployment pipeline exists to track.

Summary

GitLab Flow addresses a specific gap in GitHub Flow: the lack of explicit branches modeling a multi-stage deployment pipeline. It retains GitHub Flow's simple foundation — one `main` branch, short-lived feature branches, pull requests — while adding one or more additional, long-running **environment branches** (such as `pre-production` and `production`), each representing exactly what's currently deployed to that specific stage. Changes follow GitLab Flow's key **'upstream first'** principle: merging into `main` first, then flowing downstream toward environment branches in order, never skipping `main` or flowing backward. This makes `main` the single, consistent source of truth for all development work, while environment branches serve purely as accurate, trackable deployment state indicators — directly visible through Git history rather than requiring a separate external deployment dashboard. GitLab Flow occupies a genuine middle ground between GitHub Flow's radical simplicity and Git Flow's full five-branch-type structure, adding just enough additional structure to model real, multi-stage deployment pipelines without the overhead of a separate `develop` branch or formal release/hotfix distinction.

Frequently Asked Questions

It's a branching strategy that builds on GitHub Flow's simple main-branch foundation, adding environment branches (like pre-production and production) that explicitly represent and track a team's multi-stage deployment pipeline.

GitHub Flow assumes a fairly direct path from main to production, without explicitly modeling intermediate deployment stages like staging. GitLab Flow adds environment branches specifically to make these stages visible and trackable directly through Git history.

It means changes must always be merged into main first, and then flow downstream toward environment branches in order — never merged directly into a downstream environment branch while skipping main, keeping main the single, consistent source of truth.

GitLab Flow is generally simpler than Git Flow — it doesn't have a separate develop branch or formal release/hotfix branch types. It adds environment branches on top of a GitHub Flow-like base specifically for tracking deployment stages, without Git Flow's fuller five-branch-type structure.

Probably not — if your deployment process is simple and single-stage, GitHub Flow alone likely serves you well without the added complexity of environment branches, which are specifically valuable when a genuine multi-stage deployment pipeline exists to track.