Gitlab Merge Request Approvals: Enforce Code Review Before Deployment

Gitlab Merge Request Approvals

You've probably been there. A critical bug ships to production at 3am. The on-call engineer traces it back to a merge request that went straight to main—no review, no second pair of eyes, just one developer hitting "Merge" and hoping for the best.

That's the problem with optional code reviews. They work great until they don't, and by then, your customers are already complaining. Gitlab's merge request approval system turns code review from a suggestion into a requirement, blocking deployment until the right people sign off.

Why Merge Request Approvals Matter

Code review isn't just about catching bugs (though that's huge). It's about knowledge sharing, maintaining standards, and preventing single points of failure. When you enforce approvals, you're forcing your team to actually look at each other's code before it hits production.

What approvals prevent:

  • Unauthorized changes to critical files
  • Code that doesn't meet team standards
  • Knowledge silos where only one person understands key systems
  • Deployments that skip security reviews

Infrastructure cost: ~$20-30/month on Elestio (2 CPU / 4GB RAM) - far less than the cost of production incidents from unreviewed code.

Setting Up Required Approvals

Gitlab's approval rules live at the project level. Here's how to enforce them:

Navigate to Settings:

Project → Settings → Merge Requests → Approval Rules

Add a new rule:

Rule name: "Code Review Required"
Approvals required: 2
Eligible approvers: All developers with Maintainer role

Enable critical protections:

  • ✅ Prevent approval by author (no self-merging)
  • ✅ Prevent approvals by users who add commits (forces fresh review after changes)
  • ✅ Require approval from code owners (for specific files/directories)

For production branches specifically:

Protected Branches → main
→ Allowed to merge: No one
→ Code owner approval required: Yes

This setup ensures at least two people review every change, and the author can't approve their own work.

Code Owners for Path-Based Reviews

Here's where it gets powerful. You can require approval from specific people based on which files changed.

Create CODEOWNERS file in repo root:

# Security team must approve auth changes
/src/auth/**           @security-team

# Database team owns schema migrations
/db/migrations/**      @database-team

# DevOps reviews infrastructure changes
/.gitlab-ci.yml        @devops-team
/docker/**             @devops-team

# Lead architect approves core changes
/src/core/**           @lead-architect

Now when someone modifies /src/auth/login.js, the security team automatically gets notified and their approval becomes required. No more auth changes slipping through without security review.

Practical example:
A developer submits a merge request adding a new API endpoint. The code touches /src/auth/middleware.js, so Gitlab automatically requires approval from @security-team before allowing the merge.

Advanced Approval Rules

You can layer multiple approval requirements for different scenarios:

Security-sensitive rule:

Rule: "Security Review"
Files: **/*.env, **/secrets.*, /src/auth/**
Approvers: @security-team
Required approvals: 1

Production deployment rule:

Rule: "Production Release"
Target branches: main, production
Approvers: @tech-leads
Required approvals: 2

Documentation rule:

Rule: "Documentation Updated"
Files: docs/**, README.md
Approvers: @docs-team
Required approvals: 1
Applies to all MRs: No (only when these files change)

Override approvals for hotfixes:

Rule: "Emergency Hotfix"
Source branches: hotfix/*
Required approvals: 1 (reduced from normal 2)

These rules stack. If a merge request modifies both auth code and production config, it needs approvals from both security AND tech leads.

Approval Workflows in Practice

Let's walk through a real deployment flow with enforced approvals:

Developer creates merge request:

git checkout -b feature/user-export
# ... make changes to /src/api/users.js
git push origin feature/user-export

Gitlab checks approval rules:

  • Files changed: /src/api/users.js, /docs/api.md
  • Required approvals: 2 general + 1 from @api-team (code owner)
  • Status: ❌ Merge blocked until approvals received

First reviewer approves:

  • @jane-developer reviews code, requests changes
  • Developer fixes issues, pushes new commits
  • Gitlab resets approval (because code changed)
  • @jane-developer reviews again, approves
  • Status: 1/2 general approvals, still needs @api-team

API team lead reviews:

  • @api-lead checks API design, approves
  • Status: 2/2 general approvals + code owner approval
  • Merge button: ✅ Now enabled

Post-merge:

  • CI/CD pipeline runs automatically
  • Code ships to production with confidence

Common Pitfalls

Problem: Too many required approvals slow down development

Solution: Use different rules for different branch types. Require 2+ approvals for main, but only 1 for feature branches merging to develop.

Problem: Approvers are bottlenecks (on vacation, too busy)

Solution: Approve by role, not individual. Set eligible approvers as @senior-developers (group) instead of @specific-person.

Problem: Developers gaming the system with trivial approvals

Solution: Enable "Prevent approval by users who add commits" so reviewers can't just push a tiny change and self-approve.

Problem: Urgent hotfixes blocked by approval rules

Solution: Create a separate approval rule for hotfix/* branches with reduced requirements (1 approval instead of 2).

Integrating with CI/CD Pipelines

Approval rules work seamlessly with Gitlab CI/CD. Here's a pipeline that runs additional checks after approval:

# .gitlab-ci.yml
stages:
  - test
  - security-scan
  - deploy

unit-tests:
  stage: test
  script:
    - npm test

security-scan:
  stage: security-scan
  script:
    - npm audit --audit-level=high
  only:
    - merge_requests
  when: on_success

deploy-production:
  stage: deploy
  script:
    - ./deploy.sh production
  only:
    - main
  when: manual  # Requires manual trigger after merge
  needs:
    - job: unit-tests
    - job: security-scan

With this setup:

  1. Developer creates MR → automated tests run
  2. Reviewers approve → merge allowed
  3. After merge to main → manual deployment requires additional click

You can even block merging until CI passes:

Settings → Merge Requests → Merge checks
→ Pipelines must succeed: ✅ Enabled

Audit Trail and Compliance

One underrated benefit: approvals create an audit trail. For compliance-heavy industries (finance, healthcare), you can prove who reviewed what and when.

View approval history:

Merge Request → Approvals tab
→ See all approvers, timestamps, and reset events

Export approval data via API:

curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/1/merge_requests/5/approvals"

This audit trail is invaluable for security incidents ("Who approved the commit that introduced the vulnerability?") and compliance audits ("Can you prove all production changes were reviewed?").

Deploying Gitlab on Elestio

Ready to enforce code review in your team? Deploy Gitlab on Elestio's managed infrastructure:

Quick setup:

  1. Select Gitlab from Elestio marketplace
  2. Choose provider (Hetzner, DigitalOcean, etc.) - 2 CPU / 4GB RAM minimum
  3. Click "Deploy Service"

Once deployed, configure approval rules immediately:

  • Navigate to your project's Settings → Merge Requests
  • Add approval rules before inviting your team
  • Set protected branches for main and production

For custom domain setup with automated SSL, follow the official Elestio documentation.

Summary

Gitlab's merge request approvals transform code review from optional to mandatory. By requiring sign-off from the right people before deployment, you catch bugs earlier, share knowledge across the team, and maintain code quality without slowing down too much.

Start simple:

  • Require 1-2 approvals for all merge requests
  • Add code owners for critical paths (auth, database, infrastructure)
  • Prevent self-approval
  • Adjust rules based on branch importance

You'll ship fewer bugs, onboard new developers faster, and sleep better knowing production changes have been reviewed by someone other than the person who wrote them.

Ready to deploy Gitlab with enforced code review? Deploy Gitlab on Elestio and start protecting your production deployments today.

Thanks for reading ❤️


Published by Michael Soto, Senior Content Strategist @ Elest.io