这篇讲同事发来拉取请求、请你看代码时,从哪里下手。看完你可以在侧栏 评审 页打开差异(Diff,即改动前后的对比),对具体的行写意见,必要时用 suggestion 给出替换代码,再提交 批准、请求更改 或 评论。

拉取请求(Pull Request,也叫合并请求)是把一个分支上的改动申请合进另一个分支的请求。AngusGit 界面上叫它 拉取请求,和 GitLab 的 Merge Request、GitHub 的 Pull Request 是同一件事。要注意的是,行评和建议都在侧栏的 评审 页里写,拉取请求页本身不提供这个入口。如果想让仓库强制要求「必须评审才能合并」,可以看文末参考文章里的分支保护一文。

下文以还开着的 xlliu/test-cicd-example #1 为例,它的标题是「SC-02/SC-04 PR trigger verification」,从源分支 verify-pr-sc0204 合向目标分支 main。Angus 在这条请求上的评审仍是 待评审,在 文件变更 里可以展开差异。如果想回看一次完整的评审对话,可以打开两条已经合并的例子:xlliu/test-pr-example 的 #1 和 xlliu/test-review-example 的 #1。

一次评审的来回:批准、请求更改、评论

1. 三种结论分别意味着什么

评审的最后一步,是在三种结论里选一个。先弄清它们的区别,看代码时就知道自己要找什么。

结论 意思 对合并的影响
批准 我看过了,同意合进去 计入批准人数,人数够了合并卡才放行
请求更改 这些问题要先改完 作者改完并重新获得批准前,合并卡显示还不能合并
评论 有疑问或建议,但不挡合并 不计入批准,也不阻止合并

拿不准时选 评论,把疑问写清楚,等作者回答后再决定批准还是请求更改。如果发现某处问题会导致线上出错,就要选 请求更改,因为批准之后再补一句「记得改」,并不能拦住合并。

2. 打开要评审的那一条

  1. 进入评审列表 在侧栏点 评审,进入页头为 代码评审 的页面。默认停在 待评审 页签,这里列的是还等你处理的请求,卡片上标着 已逾期 的可以优先处理。如果同一条拉取请求指派了多位评审人,列表里会按评审人各出现一行。
  2. 找到要评审的请求 请求多的时候,可以在「搜索评审...」框里按标题搜,或者把仓库筛选从 所有仓库 换成具体的仓库。
  3. 打开评审详情 点卡片进入评审详情。顶部的统计会显示这次改动包含几个提交、几个文件,以及新增和删除的行数。随时可以点 查看拉取请求 回到这条请求的原页面。

以 Angus 的评审列表为例:待评审 是 6,已评审 是 18,顶部有搜索框、所有仓库 和 选择评审人 三个筛选。列表里有三条请求,分别是 xlliu/test-pr-example 的「docs: 说明空购物车不计算折扣 #9」(描述里写的是 Closes #4)、anguskit/Markdown 的「docs: cross-repo review list count fixture (round 25) #2」和 xlliu/test-cicd-example 的「SC-02/SC-04 PR trigger verification #1」,后两条都标着 已逾期。因为每条请求都指派了两位评审人(例如 #9 是 Angus 和 admin),所以它们在列表里各占两行。

评审待办:待评审 6,已评审 18

3. 先看作者想做什么

打开评审详情后,先别急着看代码,而是在 讨论 页签读作者写的描述:这次要解决什么问题、改动范围有多大、有没有特别希望你看的地方。不清楚改动目的就直接看差异,很容易只挑出格式问题,却漏掉真正的逻辑错误。

同一页上还有 状态检查,也就是流水线等自动检查写回来的结果,每一项显示为 成功、失败 或 进行中。如果有一项 失败,先看失败的是哪一项:要是和你要评审的代码有关,例如编译不过或测试没通过,可以直接请求更改,请作者先让检查通过。

4. 逐个文件看差异,对具体的行写意见

弄清改动目的之后,切到 文件变更 页签开始看代码。

  1. 按文件树一个个看 左侧是 文件树。每看完一个文件,就在树上勾选它,标记为 已查看;文件多的时候,这样能避免漏掉被重命名或删除的文件。大文件默认只显示前面一部分,点 展开完整 Diff 可以看到全部内容。
  2. 选一种看得顺的视图 统一视图 把删除的行和新增的行上下排在一起,适合看小改动;分栏视图 左边是修改前、右边是修改后,适合看被大段重写的函数。
  3. 在要讨论的行上留言 把鼠标移到要讨论的那一行,点 对该行添加评论,写下意见后点 评论。这时评论还是 草稿,作者看不到,所以你可以继续看其他文件、写其他行评,最后一次性发出。如果需要和同事讨论某一行,可以点 复制行链接 发给他。

文件变更:index.js 第 9 行的草稿评论

上图以 xlliu/test-cicd-example #1 的评审页为例:在 文件变更 的 统一视图 里,对 apps/service-a/src/index.js 新增的第 9 行写了一条评论。这条评论标着 草稿,作者还看不到;左侧文件树上的两个文件也都还没有标记为已查看。

写行评时注意下面三点,作者能更快改对:

  • 说清楚问题是什么,以及为什么是问题。「这里会空指针」比「这里有问题」有用得多。
  • 分清必须改的和只是建议的。如果只是个人偏好的写法,可以在开头注明「可选」,作者不改也不影响你批准。
  • 能给出代码时就直接给出,写法见下一节。

5. 直接给出替换代码

有些意见用文字很难说清,这时不如直接写出改好的代码。做法是在行评里放一个 suggestion 代码块,块里写的就是你希望这一行变成的样子:

这里没有处理 raw 为空的情况,建议先判断一下: ```suggestion if (raw == null || raw.isBlank()) return false; ``` 

发出之后,这条评论会显示为 建议的变更。作者或有写权限的人点 应用建议 后,AngusGit 会用块里的内容替换你评论的那一行(块里可以写多行),并在源分支上生成一个新提交,成功后显示 已应用。

使用建议时注意三点:

  • 建议是按行号替换的。如果你写完建议后作者又改过这个文件,行号可能已经错开,所以应用前先刷新差异,确认那一行还是你要改的那一行。
  • 一条评论只识别第一个 suggestion 块。要改几处不相邻的代码,就分成几条行评来写。
  • 应用建议会直接往作者的分支上加提交。即使评审人自己有写权限,也最好先和作者说一声再点,免得作者本地还有没推送的改动,之后推送时产生冲突。

另外,如果拉取请求的源分支在 Fork 仓库(从别人的仓库复制出来的个人副本)里,或者要改的是二进制文件,就不能应用建议。这时把代码写在普通评论里,请作者自己修改。

6. 提交结论

所有文件看完之后,点顶部的 提交评审,弹出的对话框说明是「选择你的评审决定并添加评论」。

  1. 选择决定 在 批准、请求更改、评论 中选一个,含义见第 1 节。
  2. 写一段总评 在 评论 框里写给作者的整体结论。批准时一句话就够,例如「逻辑没问题,可以合」;请求更改时,列出必须改的几处,这样作者不用自己从十几条行评里分辨哪些是必须改的。
  3. 发出 按钮上的 +N 表示会把你之前写的 N 条草稿行评一起发出。确认无误后点 提交评审。

提交之后,你的结论会出现在拉取请求 对话 页的审查区,作者也能在文件差异上看到你的每一条行评。同时,这条请求会从你的 待评审 移到 已评审。

提交评审:选中请求更改,按钮带 +1

上图的对话框里选中了 请求更改,按钮上的 +1 就是前面那条草稿行评,点 提交评审 时会一起发出;总评可以留空。在点 提交评审 之前,这条评审的状态仍是 待评审。

7. 作者改完之后,再审一遍

作者收到 请求更改 后,在本地按意见修改,再推送到同一个源分支。不需要新建拉取请求,新提交会自动出现在原来这一条里。

某条讨论按意见改好之后,作者或评审人可以点 标记为已解决。如果仓库要求合并前解决所有评论,没有标记的讨论会一直卡在合并条件里。

作者推送之后,回到这条评审再看一遍:

  1. 在 提交 页签找到作者新推的几个提交,点 查看变更,只看这次新改的内容,不必把整个差异从头再看。
  2. 确认你提的问题都改好了;还有疑问的地方,继续写行评。
  3. 再次点 提交评审,这次通常选 批准。

之前给过 批准 的人,在作者推送新提交后,会看到自己的批准被标成 需重新评审。如果目标分支开了分支保护(针对某个分支设置的合并与推送规则),这些旧批准就不再计入人数,必须有人对最新代码重新批准,合并卡才会放行。这样能保证被批准的始终是最新那一版代码。

8. 合并在拉取请求页完成,没空时可以委托

评审页只负责给出结论,不负责合并代码。等批准人数达到仓库要求、状态检查通过、也没有冲突时,由作者或维护者回到拉取请求的 对话 页点 合并拉取请求。

如果你暂时没空评审,可以在待评审状态下点 委托,在 委托给 里选另一位成员,再点 委托。这条请求就会从你的待评审列表移到对方那里。

9. 卡住时

评审过程中遇到下面这些情况,可以按表排查:

你看到的 原因 怎么处理
评审详情里没有 提交评审 按钮 你不是这条请求的评审人,或者这条请求已经合并 请作者或仓库管理员把你加为评审人。已经合并的请求不能再提交结论
作者说看不到你的行评 行评还是草稿,你还没点 提交评审 打开 提交评审,选一个结论发出。按钮上的 +N 就是还没发出的条数
在拉取请求的 文件变更 里找不到行评入口 那一页只用来浏览,页顶写着「行级评论与建议请在评审页完成」 点 前往评审页评论,到评审页写
你已经批准,合并卡仍写着还不能合并 批准人数不够;或你批准后作者又推了提交,批准变成 需重新评审;或有冲突、状态检查没过、讨论没解决 对照合并卡上写出的那一条原因处理。是 需重新评审 就对最新的代码再批准一次
点 应用建议 提示 应用建议失败 评论里没有 suggestion 块,评论不在某一行上,文件不是文本文件,或者这条请求的源分支在 Fork 里 确认建议写在行评里、块的开头是三个反引号加 suggestion。Fork 来的请求和二进制文件,请作者手动修改

常见问题

一条请求要几个人评审?

由仓库决定。设置 → 拉取请求 里的 需要的评审人数,或者分支保护里的 必需的评审人数,填的就是合并前需要的批准数,达到之后合并卡才会放行。

选了「评论」,作者还能合并吗?

能。评论 不计入批准,也不会挡住合并。如果你担心的问题必须先改,就要选 请求更改。

评审意见写错了怎么办?

在那条讨论下面点 回复,写清楚更正的内容,作者会按最新的回复修改。如果是结论本身选错了,就再提交一次评审,换成正确的结论。

一次改动太大,看不完怎么办?

在描述或总评里请作者拆成几条小的拉取请求,每条只做一件事。改动控制在几百行以内,评审人才能真正看仔细。

小结

一次完整的评审分四步:先在 评审 里打开待办;再读描述和状态检查,弄清作者想做什么;然后在 文件变更 里逐个文件看,对具体的行写意见,能直接给代码时就用 suggestion 块;最后用 提交评审 一次发出结论。作者推送新提交之后,你只需回来看新增的改动,再提交一次结论。真正的合并,由作者或维护者在拉取请求页完成。

结论: 代码评审在侧栏 评审 页完成:逐文件写下的行评会先存为草稿,点 提交评审 选择 批准、请求更改 或 评论 后才会一并公开并计入合并条件。

参考文章