GitLab 上待久了你会发现,大家嘴上挂着的 Pull Request,在 GitLab 界面里实际叫 Merge Request。标题里的 pull requets 大概率是手误,但想表达的东西很明确:代码协作里最核心的那一环——提交合并请求、组织 Code Review、把分支安全地合回主干。我这些年带团队做代码托管迁移,被问得最多的也是这条链路。这篇文章我就把 GitLab 上从零跑通 Pull Request(下面统一按 GitLab 习惯叫 MR)的完整思路和实际操作写出来,包括环境准备、分支策略、实操步骤、常见坑点,以及和 CI/CD 怎么配合。不管你是刚把团队代码迁到 GitLab 的负责人,还是第一次在 GitLab 上提 MR 的研发新人,这篇都能直接对着用。
1. 理解 Merge Request 机制
1.1 别被名字绕晕:Pull Request 和 Merge Request 是什么关系
先说个很常见的认知差。GitHub 叫 Pull Request,GitLab 叫 Merge Request,代码托管平台不同,名字不同,但解决的是同一个问题:你想把某个分支的改动合到另一个分支(通常是主干),不能直接 push 上去,而是先在平台上发起一个申请,让相关人员审查这批改动,确认没问题后再执行合并。这个机制背后的核心价值不是"合并"这个动作,而是"审查"这个过程。
GitLab 之所以叫 Merge Request,是因为它的设计更强调"请求被合并"这个结果状态,并且从诞生起就把它和 Issue、CI/CD、权限模型深度绑在了一起。实际使用中,一个 MR 可以关联 Issue、触发流水线、指定 reviewer、做多轮讨论,甚至可以设置合并前必须通过的检查项。这些能力如果只靠直接 push 分支来干活,是完全没有的。
我遇到过不少团队,刚迁到 GitLab 时还是"所有人都能 push 主干"的野路子,代码出问题都不知道谁改的。后来把主干设成保护分支、强制走 MR 流程之后,代码质量和出问题后的追溯能力明显上了一个档次。理解了这个机制背后的"审查"本质,后面所有操作环节你都能明白为什么要这么做。
1.2 分支策略:MR 能顺利流转的前提
MR 不是孤立的功能,它和你采用的分支策略强相关。常见的分支模型有三种。第一种是 GitHub Flow,主干长期存在,开发分支从主干拉出,提交 MR 合回主干,适合持续交付的互联网产品。第二种是 Git Flow,有 main、develop、release、feature、hotfix 多类分支,适合有固定发版周期的项目。第三种是 GitLab Flow,在 GitHub Flow 基础上增加了环境分支(如 staging、production),适合需要按环境逐级上线的场景。
分支策略怎么选,直接影响 MR 的粒度和审查效率。比如团队做的是每周发版一次的 ToB 产品,用 Git Flow 更合适,MR 从 feature 到 develop,再从 develop 到 release,每一层的合并都是一次质量闸门。而如果是 SaaS 产品一天发版多次,GitHub Flow 更省事,MR 直接打到 main,配合 CI 保证质量。
我个人比较推荐中小团队用 GitLab Flow 的简化版:main 分支始终可部署,功能从 main 拉分支,测试环境直接用该分支的 MR 流水线产物,验收通过后再合回 main。这样 MR 既承担了代码审查的职责,又承担了环境发布的入口。分支策略不在多,在于团队能不能一致执行,定了就写进 README 或者 CONTRIBUTING 文档里,让 MR 模板自动带上说明。
1.3 保护分支与权限模型
MR 能落地的另一个前提是权限模型要设对。GitLab 里通过保护分支(Protected Branch)来限制谁能直接 push、谁能合并 MR。以 GitLab 默认的 Protected 设置为例,main 分支默认是保护状态,只有 Maintainer 及以上角色才能直接 push,其他人只能通过 MR 合并。
这里有一个非常关键的权限级别认知:Guest、Reporter、Developer、Maintainer、Owner 这五个角色,权限逐级递增。Developer 可以创建分支、提交 MR、处理 review 意见,但没有权限合并到受保护的主干分支;Maintainer 可以合并受保护分支的 MR,也可以调整保护规则。实际设置保护分支时,可以把"允许合并"设置为 Maintainer,把"允许推送"设置为"仅 Maintainer"或者完全不开放,具体看团队的自治程度。
设置保护分支的操作路径是:项目设置 -> Repository -> Protected branches,输入分支名,选择允许合并和允许推送的角色。这里有三个值得注意的点。第一,保护分支的规则支持通配符,比如 release/* 可以一次保护所有 release 前缀的分支。第二,如果设了 "Allowed to merge" 但没设 "Allowed to push",Developer 角色还是能通过 MR 合入代码。第三,紧急修复时如果需要直接 push 主干,不用改保护规则,可以临时在 MR 界面勾选 "Allow commits from members who can merge" 或者使用 Maintainer 账号操作,但事后要在周会上复盘为什么走了紧急通道。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 准备一套能跑通 MR 的环境
2.1 服务端:用 Docker 快速部署 GitLab
要正经用 MR,先得有一个能跑的 GitLab 实例。很多团队的内网 GitLab 都是拿 Docker 部署的,原因很直接:一条命令能跑起来,升级和管理都相对省心。GitLab 官方提供了社区版镜像 gitlab/gitlab-ce,部署时需要注意几个关键配置,否则后患无穷。
最核心的一个坑是 external_url。GitLab 会把 external_url 写进项目的 clone 地址和很多内部链接里,所以必须设成容器外部能访问到的地址,比如 http://gitlab.example.com 或者 http://192.168.1.100:8929。如果这里设置了 localhost,团队其他成员 clone 代码时就会拿到一个指向自己本机的地址,直接拉不下来。
再一个是端口映射。GitLab 容器内部有 80、443、22 三个常用端口,分别对应 HTTP、HTTPS、SSH。很多团队不规划直接映射,结果主机 80 被占用只能改乱映射,导致 HTTP 地址和 SSH 地址不一致,非常难受。我建议按下面这种方式映射:
bash复制docker run -d \
--name gitlab \
--hostname gitlab.example.com \
-p 8929:80 \
-p 2289:22 \
-p 8443:443 \
-v /srv/gitlab/config:/etc/gitlab \
-v /srv/gitlab/logs:/var/log/gitlab \
-v /srv/gitlab/data:/var/opt/gitlab \
--restart always \
gitlab/gitlab-ce:latest
把容器的 80 映射到主机的 8929,22 映射到 2289,主要是避免和本机已有的 Web、SSH 服务冲突。这时记得在 /etc/gitlab/gitlab.rb 中配置 gitlab_rails['gitlab_shell_ssh_port'] = 2289,不然界面上显示的 SSH clone 地址还是默认的 22 端口。第一次启动后 GitLab 初始化需要几分钟,可以在容器日志里看到 gitlab Reconfigured! 表示就绪。
还有一个容易踩的坑是服务器内存。GitLab 整体比较吃资源,官方推荐 4GB 内存起步,亲测 2GB 内存的机器跑起来 CPU 会频繁告警,MR 操作和流水线都可能受影响。如果只有 2GB,可以关掉一些不需要的组件(比如 Prometheus、Grafana),在 gitlab.rb 里设置 prometheus_monitoring['enable'] = false,也能稍微缓解。部署完成之后,默认管理员账号是 root,首次访问会让你设置初始密码。
2.2 客户端:SSH 密钥与 Token
服务端跑起来之后,开发本地要把代码拉下来、推上去,首先要解决认证问题。GitLab 支持 HTTP(S) 和 SSH 两种 clone 方式,SSH 免密且不容易被密码策略打断,所以团队协作我强烈推荐用 SSH。
SSH 密钥的配置步骤是:本地生成密钥对 ssh-keygen -t ed25519 -C "your_email@example.com",然后把公钥(~/.ssh/id_ed25519.pub 的内容)添加到 GitLab 的用户设置里。具体路径是右上角头像 -> Preferences -> SSH Keys,把公钥粘贴进去,设个过期时间。私钥留在本地,并通过 ssh -T git@gitlab.example.com(注意端口如果是 2289,需要 ssh -T -p 2289 git@gitlab.example.com)测试是否通。网上很多教程因为没带上 -p 端口直接报错,这一步最容易卡住。
Token 的使用场景比 SSH 更广,尤其是在命令行调用 API、IDE 集成、CI/CD 配置里。GitLab 有个人访问令牌(Personal Access Token)和项目访问令牌(Project Access Token),生成路径是 Preferences -> Access Tokens。生成时一定要选对 scope:读仓库用 read_repository,写仓库用 write_repository,调用 API 用 api。Token 生成后只会显示一次,务必先复制保存,刷新页面就再也看不到了,只能重新生成。
这里有个热搜词经常搜到的问题:"gitlab login failed. check api token or gitlab version. log in via git if the versi..."。这个报错通常出现在 VSCode 的 GitLab 扩展或某些第三方工具中,原因是 API 接口不兼容:GitLab 更新后废弃了旧版本的 API,而你配置的 Token 过期或者权限不足。排查顺序是:换新 Token 试试,看用户头像下拉菜单里 Token 是否存在且 scope 正确;确认 GitLab 版本和扩展支持的版本范围是否匹配;最后验证 Ticket 能否正常调用 API,比如 curl --header "PRIVATE-TOKEN: <token>" "http://gitlab.example.com/api/v4/user" 返回 200 就说明 Token 本身没问题。
2.3 本地 IDE:VSCode 配好 GitLab
实际写代码时,很少有人愿意一直开浏览器操作 MR,把 GitLab 集成到 VSCode 里能省很多切窗口的功夫。VSCode 有官方推荐的 GitLab Workflow 扩展,安装后按 Cmd+Shift+P(Windows 是 Ctrl+Shift+P)输入 GitLab: Authenticate,选择 GitLab 实例类型,输入服务器地址和 Personal Access Token,就能在左侧面板看到自己的 MR、Issue 和流水线状态。
这里有个使用细节:GitLab Workflow 扩展感知的是当前打开的 Git 仓库所在的项目,如果你的仓库是通过 SSH clone 的,并确保本地分支名和远端一致,扩展能直接提供 "Create Merge Request" 操作。如果遇到扩展里看不到仓库内容,多半是 Token 的 scope 缺了 read_api 或者 api,重新生成一个带全权限的 Token 就好。
我团队里还有几个同事用 JetBrains 系 IDE,GitLab 集成主要是通过 Git Integration 插件实现,操作逻辑和 VSCode 类似,核心都是配置好 Token + 项目地址。不管用哪个 IDE,你都需要理解一个原则:IDE 里的 GitLab 插件本质上是封装了 GitLab API 的客户端,所有操作(创建 MR、查看流水线、处理评论)最终都是走 API,所以 Token 的权限必须给足,否则就会出现"能拉代码但不能提 MR"的怪现象。
3. 从提交代码到发起 Merge Request
3.1 本地分支管理与提交
现在环境齐了,开始走 MR 的核心流程。第一步是保证本地代码是最新的。这里我非常建议用 git fetch 而不是 git pull。git pull 默认会做 merge,容易产生一堆无意义的 merge commit,污染提交历史。git fetch 只更新远端追踪分支,然后基于 origin/main 拉新分支,历史干净清爽。
具体操作:
bash复制git fetch --all --prune
git checkout main
git pull --ff-only origin main # 仅在能快进的情况下拉取,避免自动 merge
git checkout -b feature/your-task
分支命名要有可读性。我团队约定格式是 type/issue-id-short-title,比如 feature/123-login-page、fix/456-timeout-bug,这样一看分支就知道任务类型和关联的 Issue。在 MR 里也能直接关联到对应的工作项,审查人不需要反复问"这个分支是干嘛的"。
提交代码时,commit message 用 Conventional Commits 规范最稳妥:feat: 增加登录页、fix: 修复超时 bug、refactor: 重构接口层。GitLab 的 MR 界面会默认把 commit message 作为 MR 标题的建议值,规范了 commit,MR 标题也跟着干净。提交时注意不要把密钥、数据库地址、大文件塞进去,.gitignore 一定要提前配好,否则推到远端再清理历史是一件非常痛苦的事。
3.2 推送到远端并创建 MR
代码提交完就可以推送到远端了。创建 MR 有两种方式:命令行推送后 GitLab 会打印一个创建 MR 的链接,直接复制到浏览器打开;或者在 VSCode GitLab 扩展里选中分支点 "Create Merge Request"。两者本质都是跳转到平台的 MR 创建页面。
推送命令很常规:
bash复制git push -u origin feature/123-login-page
这时终端会输出类似 remote: To create a merge request for feature/123-login-page, visit: http://gitlab.example.com/xxx/-/merge_requests/new?merge_request%5Bsource_branch%5D=feature/123-login-page 的信息,这个链接就是当前分支专用的 MR 创建入口。我建议大家养成"推送后直接盯着终端复制链接"的习惯,尤其是手上管着多个功能分支时,从终端拿链接比去网页搜索分支再创建要快得多。
如果团队用 VSCode 多,也可以在代码提交后通过 GitLab 扩展直接创建 MR,它会自动帮你填好 source branch、target branch,你只需要补充描述和 reviewer。但不管怎么创建,最终都会落到浏览器的 MR 编辑页。
这里有个特别容易犯的低级错误:目标分支选错。很多新人拉分支的时候是基于 main 拉的,但 MR 目标分支默认是继承仓库的默认分支,如果团队默认分支是 dev,而你希望合到 main,就要在 MR 页面手动切换 target branch。这个错误一旦合并出去,轻则代码进错分支,重则引发一堆冲突,所以提交前一定要确认页面顶部显示的 source: feature/xxx -> target: main。
3.3 MR 描述与审查人设置
MR 创建页面有很多字段,真正值得写好的其实是 Title 和 Description。很多人的 MR 描述只写"实现登录功能",这种描述对审查人几乎没有帮助。我建议按下面的模板来写:
- 变更背景:为什么要做这个改动,关联的 Issue 链接
- 改动内容:涉及哪些模块、哪些文件,核心逻辑是什么
- 自测情况:本地跑过的测试、手工验证过的场景
- 影响的接口/页面:上线前需要关注哪些点
- 特殊的部署/迁移注意事项:有没有数据库变更、配置变更
在 MR 编辑页右侧可以设置 Assignee(处理人)、Reviewer(审查人)、Milestone(里程碑)、Labels(标签)。新团队最常见的冲突就是"不知道该 Assign 给谁",我建议 Assignee 填 MR 的创建者自己,Reviewer 填至少一个比你熟悉这块代码的人。审查人可以通过在 Reviewers 输入框搜索用户名来添加,多人审查也支持。
GitLab 还有一个很实用的功能叫 "Squash commits when merge is accepted"。如果你的分支上提交了很多中间调试 commit,可以在 MR 页面打开这个选项,合并时 GitLab 会把所有提交压缩成一个。至于合并后是否删除源分支,页面也有一个勾选项,默认勾选,建议保持勾选,否则远端会堆积大量已经合完的功能分支,看起来非常乱。
4. Code Review 与合并策略
4.1 Review 流程设计与协作节奏
MR 创建完了,真正的价值开始于 Code Review。很多团队把 review 当成走过场,点个 approve 就算完事,这其实把 MR 最重要的质量闸门给废了。我观察下来,好的 review 节奏是:MR 关联 Issue -> 提交 MR 后立即通知 reviewer -> reviewer 在当天内完成第一轮 review -> 开发者在 review 意见下回复并修改 -> 全部 resolved 后由 Maintainer 完成合并。
GitLab 的 review 体验适合异步协作。reviewer 可以在 MR 的 Changes 标签页对具体代码行发评论,这些评论会以 thread 的形式存在,开发者可以直接在下面回复。建议在提交 MR 前自己先 review 一遍自己的 diff,很多低级问题(调试日志没删、变量命名不一致)自己就能发现,而不是等别人提出来。
一个实用的技巧是给 MR 设置"auto-merge"和"merge when pipeline succeeds"。当 CI 还没跑完但你希望流水线通过后自动合并时,可以点击 Merge 旁边的倒三角选择 "Merge when pipeline succeeds",这样流水线一绿 MR 就自动合了,不用一直盯着页面。但要特别注意,这个功能只对有合入权限的人开放,且要求该 MR 没有未解决的 discussion。
4.2 合并方式怎么选
GitLab 的合并方式有三种常用选项,很多人从来不管默认值,结果历史变得乱七八糟。我来逐个解释清楚。第一种是 Merge Commit,这是 GitLab 默认方式,会保留一条 Merge branch 'xxx' into 'main' 的合并记录,适合需要保留完整开发历史的项目。第二种是 Squash and Merge,把 MR 的所有提交压成一个再合并,适合功能分支上有一堆 fix typo、wip 这类中间提交的场景,能让主干历史非常干净。第三种是 Rebase and Merge,GitLab 先把你的分支 rebase 到目标分支上,再做快进合并,好处是历史是线性的,但代价是提交者信息会被改写,团队里有强制签名要求时要慎用。
我个人的建议是,小团队或互联网快速迭代团队优先用 Squash and Merge,配合规范化的 MR 标题,主干历史能保持极好的可读性。而采用严格 Git Flow 的 ToB 项目,多用 Merge Commit,因为发版时通过 merge commit 可以清楚看到某个 feature 是在哪个节点合入的。
4.3 CI/CD 与 Merge Request 的联动
MR 的合并不能只看人,还得看机器。GitLab CI/CD 和 MR 天然深度集成,你可以在 MR 页面的 Pipelines 标签里看到当前分支的流水线状态,并在 Rules 里设置"流水线通过后才能合并"。
经常有团队问:Jenkins 和 GitLab 能否运行在同一台主机的 Docker 上?我的答案是能,但要注意资源竞争。GitLab 本身吃内存,Jenkins 的构建任务也吃 CPU 和内存,如果两者跑在同一台低配机器上,流水线会很慢。配置上,Jenkins 通过 GitLab Plugin 接入时,需要在 GitLab 里生成一个具有 api scope 的 Access Token,并把 Webhook 指向 Jenkins 的接口地址。如果两者同在 Docker 网络里,服务名互相访问是可行的,比如 Jenkins 容器里配置 GitLab 地址时用 http://gitlab:80 这种 Docker 网络别名,比用宿主机 IP 更稳定。
在 MR 流程里启用 CI 检查,最关键的是设置 "Pipelines must succeed" 选项。路径是项目设置 -> General -> Merge requests -> Merge checks,勾选 "Pipelines must succeed" 和 "All threads must be resolved"。这个开关打开后,流水线没跑完或者 review 评论没解决,MR 页面上的 Merge 按钮就是灰的,从根本上杜绝了"人先合了,CI 再说"的习惯。
5. 常见问题排查与避坑实录
5.1 认证登录类问题
很多团队刚部署完 GitLab 会遇到"422 登录错误,但隐身模式可以登录"这个诡异现象。这个问题的根源通常是浏览器缓存了旧的 CSRF Token 或者 Cookie 过大,而 GitLab 对请求体大小有限制。解决方式按优先级尝试:清除该站点下的 Cookie 与缓存;换隐身模式验证是不是浏览器问题;如果是团队普遍出现,检查 nginx 配置里 client_max_body_size 是否过小,尤其是用 Docker 映射端口后,默认配置有时会丢参数。
"gitlab login failed. check api token or gitlab version" 这个问题的排查思路我在第 2.2 节已经讲了一部分,这里再补充一点:如果你使用的 IDE 插件一直报这个错,但浏览器登录是正常的,说明问题不在账号密码,而在 API 兼容性。GitLab 从 12.x 到 16.x 的 API 有几次 breaking change,老版本的插件或者 Jenkins/Gerrit 插件可能解析不了新版本的响应格式。最直接的确认方式是 curl 调用 /api/v4/version,看是否能正常返回 JSON。如果返回 401,检查 Token;如果返回 404 或者解析错误,大概率是版本兼容问题,需要升级插件或改用官方推荐的方式。
5.2 权限与数据异常
"gitlab restore 时报无权限"是另一个高频问题,多见于备份恢复场景。GitLab 的官方备份恢复流程要求使用 git 用户执行,如果在 root 或者其他用户下执行 gitlab-backup restore,会有大量文件权限错误。正确做法是切到 git 用户:sudo -u git -H gitlab-backup restore BACKUP=timestamp。同时确认备份目录和文件的所有者是 git 用户,不然恢复中途还是会因权限问题中断。
"gitlab 新建仓库在主页看不到"这个问题也经常有人问。原因通常是新建项目时选择了 Visibility 为 Private,而当前用户不是 Maintainer/Owner,所以首页的公开项目列表不会显示。在项目设置的 General -> Visibility 下可以看到可见性设置,把可见性或项目分组调整一下就能解决。还有一种可能是项目建在了某个 Group 下面,而你的账号没有加入该 Group,这样即便你是创建者,某些视角下也不直接展示。
5.3 使用习惯与协作类问题
"git账号和gitlab账号不一致,无法统计推送代码量"也很有代表性。很多人电脑上配置了全局的 user.name 和 user.email,但 GitLab 账号绑定的是注册邮箱,提交记录里显示的就是全局配置的邮箱,而不是 GitLab 邮箱。这样代码提交的贡献图和代码量统计就对不上,甚至被标记为未知提交者。
解决方法是,在 GitLab 里把所有用过的邮箱都加入账号(Preferences -> User settings -> Emails),这样会归并历史提交。更稳妥的做法是:
- 在每个仓库目录下覆盖配置:
git config user.name "你的名字"、git config user.email "gitlab注册邮箱" - 或者在全局配置里直接设成 GitLab 账号对应的邮箱。团队协同时,这一点最好写进入职文档,让新同事第一天就配好。
5.4 问题速查表
我把自己在实际维护 GitLab 过程中经常遇到的问题整理成了一个表,方便大家遇到类似情况快速对照:
| 现象 | 可能原因 | 处理手段 |
|---|---|---|
| SSH clone 地址不对 | external_url 或 ssh_port 配置有误 | 检查 /etc/gitlab/gitlab.rb 中 gitlab_shell_ssh_port,重新 reconfigure |
| 本地能 push 但页面 404 | 项目可见性或用户权限不匹配 | 检查项目 Visibility、用户在项目中的角色 |
| 无法合并 MR,按钮置灰 | 有未解决 discussion 或流水线未通过 | 逐个 resolved 评论,重新跑流水线 |
| Token 明明有效但 API 401 | scope 缺权限或 Token 已过期 | 重新生成 Token,勾选 api scope |
| 提交者不显示在贡献统计里 | 邮箱与 GitLab 账号不匹配 | 在账号设置里补充邮箱,或本地重新配置 user.email |
| MR 合并历史乱成麻 | 未选择合适的合并方式 | 按团队规范改用 Squash 或 Rebase 合并 |
| 422 登录错误 | Cookie 或 CSRF 缓存异常 | 清缓存,或检查 nginx client_max_body_size |
这个表看起来简单,但每一条的背后都是真实踩坑记录。比如"无法合并 MR 按钮置灰",我见过不止一个团队卡在这里研究权限半天,最后发现是某个老 MR 里有一条未解决的评论。所以排查时,优先级应该是先看 discussion 是否 resolved,再看流水线状态,最后才是权限配置。
6. 让 MR 成为团队效率引擎
6.1 用 MR 模板统一规范
MR 描述写得好不好,直接影响 review 效率。与其靠自觉,不如用 GitLab 自带的合并请求模板强制统一。在项目的 .gitlab/merge_request_templates/ 目录下创建 Markdown 文件,比如 default.md,内容包含背景、改动清单、自测记录、影响范围、部署注意点,并在项目设置里设为默认模板。这样团队每次创建 MR 时都会自动带上模板,reviewer 不用每次问"这个 MR 改了什么"。
模板还可以做场景化拆分,比如 bugfix.md 和 feature.md,分别在提交 bug 修复和新功能时选择。GitLab 的模板支持占位符变量,比如 {{ assignee }}、{{ source_branch }},能在创建 MR 时自动填充一些元信息。这一招对十人以上的团队效果非常明显。
6.2 CICD 里 GitLab 与 Gerrit 怎么配合
热搜词里有"cicd流程中gitlab以及gerrit的使用",这其实是一个多工具协作场景。Gerrit 是一个老牌的代码审查工具,审查粒度比 GitLab 细(按 commit 审核),而 GitLab 的 MR 更偏整体分支审查。有些公司会在 Jenkins 流水线里同时接两个系统:Gerrit 负责核心库的严格逐 commit review,GitLab 承载大部分业务项目的 MR 和 CI。
这种情况下容易踩的坑是流水线触发器冲突。两个系统都支持 Webhook,配置不当会导致一个 MR 提交触发多条流水线。我的建议是:如果以 GitLab 为主,就关闭 Gerrit 的 trigger,只用 Gerrit 做人工打分和门禁,再把 Gerrit 的结果通过 API 回调给 GitLab;反过来,如果以 Gerrit 为主,GitLab 里的 MR 就只做代码存储和记录,不要启用 GitLab CI 的自动 trigger。工具链的核心是"边缘清晰":谁做审查、谁跑构建、谁做产物归档,要在流水线设计文档里写死。
6.3 合理控制 MR 的粒度
最后一个想说的点是 MR 的粒度控制。很多新人喜欢攒很久的代码一次性提一个大 MR,几千行改动,reviewer 看完头都是大的。反过来,一个 MR 只改一行注释也意义不大。我建议的经验值是:一个 MR 的改动量控制在 200-400 行以内,且只解决一个明确的问题。如果功能实在大,可以拆成多个阶段 MR,逐步合入,每一阶段都保证可编译、可测试。
这个习惯带来的好处非常明显。reviewer 看小 MR 的心理负担小,更容易发现问题;出现线上故障时,也能更快地通过 git blame 定位到具体 MR 和责任人了。我在团队里甚至会把"MR 是否过小"作为 merge 的检查项之一,过大的就直接打回去让拆分。
说到这,我回忆起踩坑最多的时刻:刚开始推行 MR 流程时,团队有人觉得麻烦,有人觉得流程束缚,直到有一次线上事故,因为有一个 MR 的流水线没过就被强行合并,导致半个小时的故障。之后我们把"合并前必须流水线通过、review 评论必须全部解决"变成了硬规则,大家才真正意识到 MR 不是形式主义,而是保护线上环境的第一道防线。根据我的经验,MR 流程刚开始慢是正常的,坚持一两个月,团队的代码质量、新人的上手速度、出问题的修复效率,都会有肉眼可见的变化。
