GitLab教程(5): 合并请求(Merge Request)工作流

合并请求(Merge Request, MR)是GitLab代码审查和协作的核心功能。本文将详细介绍MR的创建、审查和合并流程。

什么是合并请求

# Merge Request (MR) vs Pull Request (PR)

# GitLab使用"Merge Request",GitHub使用"Pull Request"
# 功能基本相同:
# 1. 请求将一个分支的更改合并到另一个分支
# 2. 代码审查
# 3. 讨论和反馈
# 4. CI/CD自动运行
# 5. 最终合并

# MR工作流程
┌─────────────────────────────────────────────────────────────┐
│  1. 创建分支  →  2. 开发提交  →  3. 创建MR                 │
│       ↓              ↓              ↓                       │
│  4. 代码审查  →  5. CI通过  →  6. 合并到主分支              │
└─────────────────────────────────────────────────────────────┘

创建合并请求

从分支创建MR

# 方式1: 推送后创建
# 推送新分支后,GitLab会显示创建MR的链接
git push -u origin feature/user-login

# 输出
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 300 bytes | 300.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote:
remote: To create a merge request for feature/user-login, visit:
remote:   https://gitlab.example.com/group/project/-/merge_requests/new?merge_request%5Bsource_branch%5D=feature/user-login
remote:
To gitlab.example.com:group/project.git
 * [new branch]      feature/user-login -> feature/user-login

# 点击链接即可创建MR

# 方式2: 从分支页面创建
# Project > Code > Branches
# 点击分支旁边的 "Merge request" 按钮

# 方式3: 从菜单创建
# Project > Merge requests > New merge request
# 选择源分支和目标分支

填写MR信息

# 创建MR页面

Title: feat: 添加用户登录功能
# 标题建议使用约定式提交格式

Description:
## 变更说明
实现了用户登录功能,包括:
- 登录表单
- 密码验证
- JWT token生成

## 相关Issue
Closes #42

## 测试说明
- [x] 单元测试通过
- [x] 本地手动测试通过

## 截图
![登录页面](url-to-screenshot)

## Checklist
- [x] 代码符合项目规范
- [x] 已添加必要的测试
- [x] 已更新文档

# 其他选项
Assignee: 选择负责人
Reviewer: 选择审查者
Milestone: 选择里程碑
Labels: 添加标签 (feature, needs-review)
Merge options:
  - Delete source branch when merge request is accepted
  - Squash commits when merge request is accepted

从Issue创建MR

# 从Issue直接创建分支和MR
# Issue页面 > Create merge request

# 自动创建:
# 1. 分支名: 42-issue-title
# 2. MR标题: Draft: Resolve "Issue title"
# 3. 描述中包含: Closes #42

# 这种方式可以确保Issue和MR关联
# 合并后Issue会自动关闭

代码审查

查看变更

# MR页面 > Changes 标签

# 显示所有更改的文件
src/
├── auth/
│   ├── login.js      (+50, -0)  新增文件
│   └── auth.test.js  (+30, -0)  新增文件
├── api/
│   └── routes.js     (+5, -2)   修改
└── package.json      (+2, -0)   修改

# 差异视图模式
- Inline: 行内显示新旧代码
- Side-by-side: 左右对比显示

# 展开更多上下文
# 点击 "..." 可以展开隐藏的代码行

# 查看单个文件完整内容
# 点击文件名旁边的 "View file" 按钮

添加评论

# 行级评论
# 将鼠标悬停在代码行号上,点击气泡图标

评论示例:
"这里应该添加错误处理,如果API请求失败怎么办?"

# 评论选项
- Start a thread: 开始讨论串
- Add suggestion: 建议代码修改

# 代码建议格式
```suggestion
const response = await api.login(credentials);
if (!response.ok) {
  throw new Error('Login failed');
}
```
# 作者可以直接点击 "Apply suggestion" 应用修改

# 批量评论
# 点击 "Start a review" 开始审查
# 添加多个评论后一起提交
# 避免发送过多邮件通知

# 标记讨论为已解决
# 问题解决后,点击 "Resolve thread"

审批流程

# 配置审批规则
# Project > Settings > Merge requests > Merge request approvals

# 审批规则示例
Rule 1: Any eligible user
  - Approvals required: 1
  - Eligible approvers: All project members

Rule 2: Backend Team
  - Approvals required: 1
  - Eligible approvers: @backend-team
  - Protected branch: main

Rule 3: Code Owner
  - Approvals required: 1
  - Eligible approvers: Code Owners

# CODEOWNERS文件
# 定义代码所有者
# 文件: .gitlab/CODEOWNERS 或 CODEOWNERS

# 默认所有者
* @default-owner

# 特定目录所有者
/src/frontend/ @frontend-team
/src/backend/ @backend-team
/docs/ @tech-writer

# 特定文件所有者
*.js @js-experts
Dockerfile @devops-team
.gitlab-ci.yml @devops-team

# 审批状态
# MR页面会显示:
# ✓ Approved by @reviewer1
# ⏳ Waiting for approval from @reviewer2

CI/CD集成

# MR创建/更新时自动运行CI

# MR页面显示流水线状态
┌─────────────────────────────────────────────────────────────┐
│  Pipeline #1234                                    Running  │
│  ┌──────┐   ┌──────┐   ┌──────┐   ┌──────┐                 │
│  │Build │ → │ Test │ → │ Lint │ → │Deploy│                 │
│  │  ✓   │   │  ✓   │   │  ⏳  │   │  ○   │                 │
│  └──────┘   └──────┘   └──────┘   └──────┘                 │
└─────────────────────────────────────────────────────────────┘

# 配置MR流水线
# .gitlab-ci.yml

stages:
  - build
  - test
  - review

build:
  stage: build
  script:
    - npm ci
    - npm run build

test:
  stage: test
  script:
    - npm run test:coverage
  coverage: '/Statements\s*:\s*(\d+\.?\d*)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

lint:
  stage: test
  script:
    - npm run lint

# MR专用的Review App
review:
  stage: review
  script:
    - deploy-review-app.sh
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://$CI_COMMIT_REF_SLUG.review.example.com
    on_stop: stop_review
  only:
    - merge_requests

stop_review:
  stage: review
  script:
    - delete-review-app.sh
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  when: manual
  only:
    - merge_requests

合并选项

# 合并策略
# Project > Settings > Merge requests > Merge method

1. Merge commit (默认)
   - 创建合并提交
   - 保留完整历史
   - git merge --no-ff

2. Merge commit with semi-linear history
   - 需要先rebase
   - 保持线性历史
   - git rebase + git merge --no-ff

3. Fast-forward merge
   - 不创建合并提交
   - 需要先rebase
   - git merge --ff-only

# Squash提交
# 将所有提交压缩成一个
# 适合小功能分支,保持主分支历史简洁

# 合并时选项
☑ Delete source branch when merge request is accepted
☑ Squash commits when merge request is accepted

# Squash提交信息
# 默认使用MR标题和描述
feat: 添加用户登录功能

* 实现登录表单
* 添加JWT认证
* 添加单元测试

Closes #42

草稿MR

# 草稿MR (Draft MR)
# 用于进行中的工作,还不准备合并

# 创建草稿MR
# 方式1: 标题以 "Draft:" 开头
Title: Draft: 添加用户登录功能

# 方式2: 创建时勾选 "Mark as draft"

# 方式3: 已有MR标记为草稿
# MR页面 > Mark as draft

# 草稿MR特点
- 显示 "Draft" 标签
- 无法直接合并
- 仍可进行代码审查
- CI仍会运行

# 取消草稿状态
# MR页面 > Mark as ready
# 或从标题中删除 "Draft:"

冲突解决

# 当MR有冲突时,无法自动合并

# MR页面显示
⚠ This merge request has conflicts.
Resolve these conflicts or ask someone with write access to this repository.

# 方式1: 在线解决冲突
# 点击 "Resolve conflicts" 按钮
# 在Web界面中选择保留哪些更改

# 方式2: 本地解决冲突
git checkout feature/user-login
git fetch origin
git rebase origin/main

# 遇到冲突
Auto-merging src/api/routes.js
CONFLICT (content): Merge conflict in src/api/routes.js
error: could not apply abc123... Add login route

# 编辑文件解决冲突
vim src/api/routes.js

# 文件中的冲突标记
<<<<<<< HEAD
const routes = ['/users', '/orders'];
=======
const routes = ['/users', '/login'];
>>>>>>> abc123 (Add login route)

# 解决后继续rebase
git add src/api/routes.js
git rebase --continue

# 强制推送更新分支
git push --force-with-lease origin feature/user-login

MR模板

# 创建MR模板
# 文件: .gitlab/merge_request_templates/Default.md

## 变更类型
- [ ] 新功能 (feature)
- [ ] Bug修复 (bugfix)
- [ ] 代码重构 (refactor)
- [ ] 文档更新 (docs)
- [ ] 测试 (test)
- [ ] 其他

## 变更说明


## 相关Issue
Closes #

## 测试说明


## 截图/录屏


## Checklist
- [ ] 代码符合项目规范
- [ ] 已添加/更新测试
- [ ] 已更新文档
- [ ] 已进行自我审查
- [ ] CI通过

## 审查注意事项


/label ~needs-review
/assign @self

快速命令

# 在MR评论中使用快速命令

# 指派
/assign @zhangsan
/assign me
/unassign

# 审查者
/reviewer @lisi
/request_review @wangwu

# 标签
/label ~bug ~critical
/unlabel ~needs-review

# 里程碑
/milestone %v1.0.0

# 时间估计
/estimate 3d
/spend 2h

# 合并选项
/merge
/draft
/ready

# 关联
/relate #42
/close #42

# 复制到其他分支
/copy_metadata main

# 审批
/approve
/unapprove

最佳实践

  • 保持MR小而聚焦:每个MR只做一件事,便于审查
  • 写好标题和描述:让审查者快速理解变更内容
  • 关联Issue:使用"Closes #123"自动关闭Issue
  • 添加测试:确保代码质量
  • 及时响应反馈:快速处理审查意见
  • 使用草稿MR:早期获取反馈

总结

本文详细介绍了GitLab合并请求的完整工作流程,包括创建MR、代码审查、CI集成和合并选项。MR是团队协作和代码质量保证的关键环节。

下一篇我们将学习GitLab CI/CD基础入门。

发表回复

后才能评论