| | |

GitLab 05 🦊 Creating, Reviewing, and Merging Merge Requests (MRs)

ā±ļø Estimated read: 11 min | |

A merge request in GitLab is the mechanism that turns a branch into a proposal. It is not a Git operation—Git has no concept of a merge request. It is a GitLab feature that wraps the branch in a review workflow: discussion, pipeline verification, and a merge gate. The exam tests the lifecycle: how the MR is created from a source branch, how the review process unfolds, and which merge method is appropriate for the project’s history policy. The critical distinction is between the MR creation (which requires a source and target branch) and the merge method (which is configured at the project level and determines how commits land on the target branch).

Key point: A merge request proposes merging a source branch into a target branch. The review process requires at least one approval and a passing pipeline before the merge button becomes active. The merge method (merge commit, semi-linear, or fast-forward) is a project-level setting that determines the shape of the history after the merge.


Why merge requests exist

The direct push problem. A branch can be merged locally and pushed to the target branch. This works, but it provides no opportunity for review, no pipeline verification, and no record of the discussion. A merge request creates a gate: the code is visible, the CI pipeline runs, the reviewers comment, and only then does the merge button become available . The MR is the audit trail.

The pipeline problem. A merge request pipeline runs against the merged result of the source and target branches. If the pipeline fails, the merge is blocked. This catches integration failures before they reach the target branch—a class of bug that a local test suite cannot detect because it runs against the source branch alone . The pipeline status is the first diagnostic signal on the MR page.

The review problem. A code review is not a comment. It is a structured evaluation with a decision: approve, or request changes. GitLab tracks the review status of each assigned reviewer: awaiting review, in progress, approved, or requested changes . The MR cannot be merged until the required approvals are satisfied. The review is the gate, not the comment.

The merge method problem. The merge method determines the shape of the target branch’s history. The “Merge commit” method creates a merge commit with two parents, preserving the branch topology. The “Fast-forward” method creates a linear history with no merge commit. The “Semi-linear” method creates a merge commit only when a fast-forward is possible, ensuring that the target branch builds after the merge . The choice is a policy decision, not a technical requirement.

The trade-off. A merge request adds process. For a solo project with no reviewers, it is an extra step. But the moment a second person is involved—or the moment a pipeline needs to run before a merge—the MR becomes the only reliable way to enforce quality.


a. Creating a merge request

A merge request is created from the GitLab web interface, the glab CLI, or a push option. The web interface is the most common path. The “New merge request” button opens a form with two dropdowns: the source branch (the branch containing the changes) and the target branch (the branch that will receive the merge, typically main or master) .

# Create via web interface
Code → Merge requests → New merge request
Source branch: feature/login
Target branch: main
Compare branches and continue
Title: Add login form
Description: Implements the login form with validation.
Assignee: yourself
Reviewer: team member
Create merge request

The title should be a concise summary of the change. The description should include the context: what changed, why, and any testing considerations. Linking the MR to an issue with Closes #123 in the description automatically closes the issue when the MR merges . The reviewer field assigns the MR to a team member; the approval is required before the merge button becomes active.

The glab CLI provides a faster path for developers who work in the terminal. The glab mr create command creates the MR from the current branch, with options to fill the title and description from commits, mark as draft, or assign reviewers .

# Create MR from current branch, fill from commits
glab mr create --fill --reviewer username

# Create as draft
glab mr create --draft --title "WIP: Login form"

b. Reviewing a merge request

The review process begins when a reviewer is assigned. The reviewer opens the MR, reads the description, and selects the “Changes” tab to view the diff. The diff shows the added, removed, and modified lines. Comments are placed on specific lines, and the reviewer can suggest changes that the author can apply with a single click .

The review has four states. “Start a review” collects comments without publishing them; the reviewer adds comments across multiple files and submits them all at once. “Approve” signals that the changes are ready to merge. “Request changes” blocks the merge until the feedback is addressed. “Comment” leaves feedback without a decision .

# Review flow
Changes tab → click line number → write comment
Start a review (collects comments)
Add more comments → Add to review
Submit your review → Approve or Request changes

The right sidebar shows the status of each reviewer: awaiting review, in progress, approved, or requested changes. A green checkmark appears next to the name of a reviewer who has approved . If the author pushes new commits after an approval, the reviewer can be asked to re-review with the “Re-request a review” icon .

The pipeline status is visible on the Overview tab. A red pipeline blocks the merge. The reviewer should check the pipeline logs before approving—a passing pipeline with warnings may still indicate a problem that the reviewer needs to address.


c. Merging and merge methods

The merge button is enabled only when the required approvals are satisfied and the pipeline has passed. The merge method is configured at the project level under Settings → Merge requests. The method determines the shape of the history after the merge .

The “Merge commit” method creates a merge commit with two parents. The feature branch’s commits are preserved, and the merge commit records the integration point. This is the default method and the most common choice for teams that want to preserve the branch topology.

The “Fast-forward” method creates a linear history with no merge commit. The feature branch’s commits are added directly to the target branch, and the target branch pointer moves forward. This is possible only when the target branch has not diverged from the source branch’s base. If it has, the source branch must be rebased first .

The “Semi-linear” method creates a merge commit only when a fast-forward is possible. This ensures that if the MR pipeline passed, the target branch will also build after the merge. If a fast-forward is not possible, the author must rebase before merging .

# Configure merge method
Settings → Merge requests → Merge method
ā—‹ Merge commit
ā—‹ Merge commit with semi-linear history
ā—‹ Fast-forward merge
Squash commits when merging: Do not allow / Allow / Encourage / Require
Save changes

The “Squash commits when merging” setting controls whether the feature branch’s commits are combined into a single commit. The options are “Do not allow” (never squash), “Allow” (squash is optional), “Encourage” (squash is on by default), and “Require” (squash is mandatory) . Squashing is useful for feature branches with many small commits (“fix typo”, “address review”), but it discards the individual commit history.

The glab mr merge command merges from the terminal. The --squash flag enables squashing, --remove-source-branch deletes the branch after merging, and --auto-merge sets the MR to merge when the pipeline succeeds .


Complete Example Session

# ============================================
# PART 1: CREATE A BRANCH AND COMMIT
# ============================================

git checkout -b feature/login
# Make changes...
git add .
git commit -m "Add login form"
git push -u origin feature/login
# ============================================
# PART 2: CREATE THE MERGE REQUEST
# ============================================

# GitLab → Code → Merge requests → New merge request
# Source: feature/login
# Target: main
# Title: Add login form
# Description: Implements login with validation. Closes #42
# Reviewer: team member
# Create merge request
# ============================================
# PART 3: PIPELINE RUNS
# ============================================

# The pipeline status appears on the MR.
# If red, the merge button is disabled.
# ============================================
# PART 4: REVIEWER OPENS CHANGES
# ============================================

# Reviewer opens the MR.
# Selects "Changes" tab.
# Adds inline comment on line 42.
# Clicks "Start a review".
# ============================================
# PART 5: REVIEWER SUBMITS APPROVAL
# ============================================

# Reviewer clicks "Submit your review".
# Selects "Approve".
# The approval count increases.
# ============================================
# PART 6: AUTHOR MERGES
# ============================================

# With approval and passing pipeline:
# Merge button is enabled.
# Click "Merge".
# ============================================
# PART 7: CONFIGURE MERGE METHOD
# ============================================

# Settings → Merge requests → Merge method
# Select "Fast-forward merge"
# Squash commits: Require
# Save changes
# ============================================
# PART 8: MERGE WITH CLI
# ============================================

glab mr merge 42 --squash --remove-source-branch
# ============================================
# PART 9: DELETE SOURCE BRANCH
# ============================================

# The "Delete source branch" checkbox is available on merge.
# Or: git push origin --delete feature/login

The nine parts trace the MR lifecycle: branch creation, MR creation, pipeline run, review, approval, merge, merge method configuration, CLI merge, and branch deletion.


Quick Reference

Merge Request States

StateMeaning
DraftNot ready for review
OpenReady for review
MergedChanges integrated
ClosedRejected or abandoned

Review Decisions

DecisionEffect
ApproveSatisfies approval requirement
Request changesBlocks merge
CommentFeedback without decision

Merge Methods

MethodHistory ShapeMerge Commit
Merge commitBranchedYes
Semi-linearBranched (if FF possible)Yes
Fast-forwardLinearNo

Squash Options

OptionBehavior
Do not allowNever squash
AllowOptional
EncourageOn by default
RequireMandatory

Best Practices

āœ… Do This:

# Link the MR to an issue
Closes #42
<!-- Auto-closes the issue on merge -->               # āœ…
# Request a reviewer before merging
<!-- Approval is required for protected branches -->  # āœ…
glab mr merge 42 --squash --remove-source-branch
<!-- Use CLI for repeatable merges -->                # āœ…

āŒ Don’t Do This:

# Merge without pipeline passing
<!-- Red pipeline blocks merge -->                    # āŒ
# Merge without approval
<!-- Protected branch requires approval -->           # āŒ
# Force push to a merged MR branch
<!-- May confuse the review state -->                 # āŒ

Common Pitfalls

PitfallWhy It HappensFix
Merge button disabledPipeline failing or approvals missingCheck MR widget
Cannot mergeTarget branch protectedRequired role or approval
MR shows stale commitsSource branch not rebasedRebase before merge
Squash not availableProject setting disallowsChange setting or use merge commit
Review comments not visibleUsed “Add comment now” instead of “Start a review”Submit review to publish

Real-World Examples

1. Create MR via Web

Code → Merge requests → New merge request
Source: feature/login → Target: main

2. Create MR via CLI

glab mr create --fill --reviewer username

3. Review Changes

Changes tab → inline comment → Start a review

4. Approve

Submit your review → Approve

5. Request Changes

Submit your review → Request changes

6. Merge

Merge button (enabled when approved + pipeline green)

7. Merge via CLI

glab mr merge 42 --squash

8. Configure Merge Method

Settings → Merge requests → Merge method → Fast-forward

9. Squash Commits

Merge request → Squash commits checkbox

10. Delete Source Branch

Merge request → Delete source branch checkbox

Visual

Merge Request Lifecycle

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Push branch to GitLab                       │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                   │
                   ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Create MR (source → target)                 │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                   │
                   ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Pipeline runs (CI checks)                   │
│  Reviewer assigned                           │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                   │
                   ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Review: Approve / Request changes           │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
           │ APPROVED              │ CHANGES
           ā–¼                       ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Merge enabled       │  │  Author fixes        │
│  (pipeline green)    │  │  Re-request review   │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Merge Methods

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Merge commit                                │
│  A --- B --- C ------- M                     │
│            \         /                       │
│             D --- E -                        │
│  (branched, merge commit)                    │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                   │
                   ā–¼
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Fast-forward                                │
│  A --- B --- C --- D --- E                   │
│  (linear, no merge commit)                   │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Summary

ItemValue
MR purposePropose merging source into target
CreationWeb UI or glab mr create
Review statesApprove, Request changes, Comment
Merge gateApprovals + passing pipeline
Merge methodsMerge commit, Semi-linear, Fast-forward
Squash optionsDo not allow, Allow, Encourage, Require
CLI mergeglab mr merge <id>
Auto-mergeSet to merge when pipeline passes

Key takeaways:

  • A merge request is a proposal, not a push. It opens a review workflow that a direct merge bypasses. The merge button is gated by approvals and a passing pipeline .
  • The review is a decision, not a comment. “Approve” satisfies the approval requirement. “Request changes” blocks the merge. “Comment” is neutral .
  • The merge method shapes the history. Merge commit preserves the branch topology. Fast-forward produces a linear history. Semi-linear creates a merge commit only when a fast-forward is possible .
  • Squash is a policy decision. The project setting controls whether squashing is allowed, encouraged, or required. Squashing combines the branch’s commits into one .
  • The CLI provides a repeatable path. glab mr create and glab mr merge script the MR lifecycle without the web interface .

Remember: The merge request is the gate between a branch and the target branch. The review is the decision. The pipeline is the verification. The merge method is the history policy. A merge request that is approved and passes the pipeline is ready to merge. A merge request that fails either gate is not.

Was this helpful?


Stop using slow, ad-bloated tool sites! 🤮

šŸ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
āœ… Finance (Mortgage, Interest, Inflation)
āœ… Tech (Base64, JSON, Dev Suite, IP)
āœ… Health (BMI, BMR, TDEE)
āœ… Productivity (Timer, Workspace, QR)

āš”ļø Fast & Private
šŸ”’ No data leaves your device
šŸ’Ž 100% Free

šŸ”— Use it now: https://tools.kandz.me
šŸ”– Bookmark it—you’ll need it later!