Files
gh-lucacri-claude-gitlab-do…/skills/gitlab/references/merge-requests.md
2025-11-30 08:38:11 +08:00

16 KiB

GitLab Merge Requests Reference

Overview

Merge Requests (MRs) are the primary mechanism for proposing changes, conducting code reviews, and merging code in GitLab.

Creating Merge Requests

Via UI

  1. Navigate to project
  2. Create/push to branch
  3. Click "Create merge request"
  4. Fill in details:
    • Title and description
    • Source and target branches
    • Assignees and reviewers
    • Labels and milestone
  5. Click "Create merge request"

Via API

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests" \
  --data "source_branch=feature" \
  --data "target_branch=main" \
  --data "title=Add new feature" \
  --data "description=This MR adds..." \
  --data "assignee_id=123" \
  --data "reviewer_ids[]=456"

Via Git Push Options

# Create MR on push
git push -o merge_request.create \
  -o merge_request.target=main \
  -o merge_request.title="Add feature" \
  origin feature-branch

# Create and assign
git push -o merge_request.create \
  -o merge_request.assign="username" \
  origin feature-branch

# Create with labels
git push -o merge_request.create \
  -o merge_request.label="bug" \
  -o merge_request.label="priority::high" \
  origin feature-branch

Via CLI

# Using glab
glab mr create --title "Add feature" \
  --description "Detailed description" \
  --source feature-branch \
  --target main \
  --assignee @username \
  --label bug,feature

Merge Request Details

Basic Information

Title: Add user authentication
Description: |
  Implements JWT authentication for API endpoints.

  Changes:
  - Add JWT middleware
  - Add auth routes
  - Add user model
  - Add tests

  Closes #123
Source Branch: feature/auth
Target Branch: main
Author: @john
Assignee: @jane
Reviewers: @alice, @bob
Labels: feature, security
Milestone: v1.0

Closing Issues

Link issues in description:

  • Closes #123
  • Fixes #456
  • Resolves #789
  • Implements #101

Description Templates

Create .gitlab/merge_request_templates/Default.md:

## What does this MR do?

<!-- Brief description -->

## Related issues

<!-- Link related issues -->
Closes #

## Author's checklist

- [ ] Tests added
- [ ] Documentation updated
- [ ] Changelog entry added
- [ ] Reviewed by peers

## Reviewer's checklist

- [ ] Code follows style guide
- [ ] Tests pass
- [ ] No security issues
- [ ] Performance acceptable

Merge Request Workflow

Draft/WIP Merge Requests

Mark as draft:

# In title
Draft: Add feature
WIP: Add feature

# Via API
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid" \
  --data "draft=true"

Remove draft status:

curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid" \
  --data "draft=false"

Assignees and Reviewers

Assignees: Responsible for the MR Reviewers: Review and approve the MR

# Set assignees
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid" \
  --data "assignee_ids[]=123" \
  --data "assignee_ids[]=456"

# Set reviewers
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid" \
  --data "reviewer_ids[]=789"

Labels and Milestones

# Add labels
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid" \
  --data "labels=bug,feature,priority::high"

# Set milestone
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid" \
  --data "milestone_id=10"

Code Review

Comments and Discussions

Add comment:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/notes" \
  --data "body=Looks good!"

Add line comment:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/discussions" \
  --data "body=Consider refactoring this" \
  --data "position[base_sha]=abc123" \
  --data "position[start_sha]=def456" \
  --data "position[head_sha]=ghi789" \
  --data "position[new_path]=src/file.js" \
  --data "position[new_line]=42" \
  --data "position[position_type]=text"

Resolvable Discussions

Mark discussions as resolvable:

  • Reviewer creates resolvable discussion
  • Author resolves after fixing
  • Must resolve all before merging (if required)
# Resolve discussion
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/discussions/:discussion_id" \
  --data "resolved=true"

Suggestions

Apply code suggestions in reviews:

```suggestion
const result = calculate(x, y);
return result * 2;

Apply suggestion:
- Click "Apply suggestion" button
- Or use API to apply

**Batch apply suggestions**:
1. Select multiple suggestions
2. Click "Apply X suggestions"
3. Commit with single commit

### Code Quality Reports

View code quality changes:
- New issues introduced
- Resolved issues
- Code quality score

Requires CI/CD job with code quality report:
```yaml
code_quality:
  image: docker:stable
  services:
    - docker:stable-dind
  script:
    - docker run --env SOURCE_CODE="$PWD" --volume "$PWD":/code \
        --volume /var/run/docker.sock:/var/run/docker.sock \
        registry.gitlab.com/gitlab-org/ci-cd/codequality:latest /code
  artifacts:
    reports:
      codequality: gl-code-quality-report.json

Merge Request Approvals

Configure Approval Rules

Via UI:

  1. Project Settings > Merge requests > Approval rules
  2. Add rule
  3. Set required approvers
  4. Set approval count

Via API:

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/approval_rules" \
  --data "name=Security Review" \
  --data "approvals_required=2" \
  --data "user_ids[]=123" \
  --data "user_ids[]=456"

Approve Merge Request

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/approve"

Unapprove

curl --request POST --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/unapprove"

Approval Settings

Require approvals:

  • Number of approvals needed
  • Eligible approvers
  • Approval groups
  • Code owner approvals

Prevent self-approval:

  • Author cannot approve own MR

Prevent committer approval:

  • Users who committed cannot approve

Require new approvals when pushed:

  • Reset approvals on new commits

Merge Strategies

Merge Commit

Creates merge commit with two parents:

     C---D feature
    /     \
A---B-------E main

Fast-Forward Merge

No merge commit when possible:

A---B---C---D main
            (was feature)

Squash and Merge

Combines all commits into one:

A---B---C main
        (squashed feature commits)

Configure in MR:

curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid" \
  --data "squash=true"

Semi-Linear Merge

Rebase then merge (no fast-forward):

     C'--D' feature
    /      \
A---B-------E main

Merging

Merge When Pipeline Succeeds

Automatically merge after pipeline passes:

curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/merge" \
  --data "merge_when_pipeline_succeeds=true" \
  --data "should_remove_source_branch=true"

Manual Merge

curl --request PUT --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/merge" \
  --data "squash=true" \
  --data "should_remove_source_branch=true" \
  --data "merge_commit_message=Custom merge message"

Merge Trains

Queue merges to prevent breaking main branch:

Enable merge trains:

  1. Project Settings > Merge requests
  2. Enable "Merged results pipelines"
  3. Enable "Merge trains"

Benefits:

  • Serialized merging
  • Pipeline runs against merged result
  • Prevents breaking main branch
  • Automatic rebase

Merge Conflicts

View Conflicts

curl --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/conflicts"

Resolve Conflicts via UI

  1. View MR with conflicts
  2. Click "Resolve conflicts"
  3. Choose conflict resolution
  4. Commit resolution

Resolve Conflicts Locally

# Fetch latest changes
git fetch origin

# Checkout source branch
git checkout feature-branch

# Merge or rebase
git merge origin/main
# or
git rebase origin/main

# Resolve conflicts in files
# Add resolved files
git add .

# Complete merge/rebase
git commit  # for merge
git rebase --continue  # for rebase

# Push
git push origin feature-branch

Merge Request Diff

View Diff

curl --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid/changes"

Diff Options

  • Inline diff: Side-by-side comparison
  • Side-by-side diff: Parallel view
  • File by file: Navigate file by file
  • Ignore whitespace: Skip whitespace changes

Download Patch

curl --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid.patch" \
  -o merge_request.patch

Download Diff

curl --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid.diff" \
  -o merge_request.diff

Merge Request Pipelines

Pipeline for Merged Results

Test merge result before merging:

.gitlab-ci.yml:

workflow:
  rules:
    - if: $CI_MERGE_REQUEST_ID
      when: always
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: always

Require Pipeline Success

Configure in project settings:

  • Pipelines must succeed
  • Required successful jobs

Merge Request Dependencies

Depend on Another MR

Use cross-references in description:

Depends on !123
Blocked by !456

Merge Request Metrics

View Metrics

curl --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests/:mr_iid"

Metrics include:

  • Time to merge
  • First comment time
  • First approve time
  • Review time
  • Diff stats (additions/deletions)

Merge Request Analytics

Project level:

  • Average time to merge
  • Throughput
  • Open MRs over time

Group level (Premium/Ultimate):

  • Cross-project metrics
  • Team performance
  • Bottleneck identification

Merge Request Automation

Quick Actions

Use in comments:

  • /approve - Approve MR
  • /merge - Merge MR
  • /close - Close MR
  • /reopen - Reopen MR
  • /assign @user - Assign to user
  • /unassign - Remove assignee
  • /label ~bug - Add label
  • /unlabel ~bug - Remove label
  • /milestone %v1.0 - Set milestone
  • /due 2025-12-31 - Set due date
  • /estimate 2h - Set time estimate
  • /spend 1h - Add time spent
  • /draft - Mark as draft
  • /ready - Remove draft status

Merge Request Webhooks

Trigger automation on MR events:

# Example CI/CD trigger
review-app:
  script:
    - deploy-review-app.sh
  only:
    - merge_requests
  environment:
    name: review/$CI_MERGE_REQUEST_IID
    url: https://$CI_MERGE_REQUEST_IID.review.example.com
    on_stop: stop-review-app

Code Owners

CODEOWNERS File

Create .gitlab/CODEOWNERS:

# Backend team owns all .rb files
*.rb @backend-team

# Frontend team owns React components
/src/components/ @frontend-team

# DevOps owns CI/CD config
/.gitlab-ci.yml @devops
/docker/ @devops

# Security team must approve sensitive files
/config/secrets/ @security-team
/lib/auth/ @security-team

# Everyone in group must approve
/docs/ @group/docs-team

Syntax:

  • path @user - User approval
  • path @group - Group approval
  • path @group/subgroup - Subgroup approval

Require Code Owner Approval

  1. Project Settings > Merge requests
  2. Enable "Require approval from code owners"
  3. Code owners must approve changes to their files

Merge Request Templates

Create Templates

Create in .gitlab/merge_request_templates/:

Feature.md:

## Feature Description

<!-- What feature does this add? -->

## Implementation Details

<!-- Technical details -->

## Testing

- [ ] Unit tests added
- [ ] Integration tests added
- [ ] Manual testing completed

## Screenshots

<!-- If applicable -->

## Related Issues

Closes #

Bugfix.md:

## Bug Description

<!-- What bug does this fix? -->

## Root Cause

<!-- What caused the bug? -->

## Solution

<!-- How is it fixed? -->

## Testing

- [ ] Bug reproduced
- [ ] Fix verified
- [ ] Regression tests added

Fixes #

Use Template

# Create MR with template
curl --request POST --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/:id/merge_requests" \
  --data "source_branch=feature" \
  --data "target_branch=main" \
  --data "title=Add feature" \
  --data "description=$(cat .gitlab/merge_request_templates/Feature.md)"

Best Practices

1. Merge Request Size

  • Keep MRs focused and small
  • Aim for < 400 lines of changes
  • Split large features into multiple MRs
  • Easier to review and test

2. Title and Description

  • Clear, descriptive title
  • Explain "why" not just "what"
  • Link related issues
  • Include screenshots/videos
  • Checklist for requirements

3. Commits

  • Atomic commits
  • Descriptive commit messages
  • Consider squashing for cleaner history
  • Sign commits for verification

4. Review Process

  • Request specific reviewers
  • Respond to all comments
  • Resolve discussions
  • Re-request review after changes
  • Thank reviewers

5. Testing

  • Add/update tests
  • Ensure CI passes
  • Manual testing in review app
  • Performance testing if needed

6. Documentation

  • Update relevant docs
  • Add API documentation
  • Update CHANGELOG
  • Include inline comments

7. Communication

  • Use discussions for questions
  • Mark as draft while working
  • Update status regularly
  • Notify when ready for review

CLI Examples

Using glab

# View MRs
glab mr list
glab mr list --assignee @me
glab mr list --state merged

# View MR details
glab mr view 123

# Create MR
glab mr create

# Checkout MR
glab mr checkout 123

# Approve MR
glab mr approve 123

# Merge MR
glab mr merge 123

# Close MR
glab mr close 123

# View MR diff
glab mr diff 123

API Examples

Python

import gitlab

gl = gitlab.Gitlab('https://gitlab.com', private_token='token')
project = gl.projects.get('group/project')

# Create MR
mr = project.mergerequests.create({
    'source_branch': 'feature',
    'target_branch': 'main',
    'title': 'Add feature',
    'description': 'Description',
    'assignee_id': 123
})

# Get MR
mr = project.mergerequests.get(1)

# Add comment
mr.notes.create({'body': 'Looks good!'})

# Approve
mr.approve()

# Merge
mr.merge()

JavaScript

const { Gitlab } = require('@gitbeaker/node');
const api = new Gitlab({ token: 'token' });

// Create MR
const mr = await api.MergeRequests.create('group/project', 'feature', 'main', 'Add feature');

// Get MR
const mr = await api.MergeRequests.show('group/project', 1);

// Add comment
await api.MergeRequestNotes.create('group/project', 1, 'Looks good!');

// Approve
await api.MergeRequests.approve('group/project', 1);

// Merge
await api.MergeRequests.accept('group/project', 1, {
  should_remove_source_branch: true,
  squash: true
});

Additional Resources