为什么写这篇文章
最近从学校毕业了,上手所在小组的项目时候,发现项目使用Gerrit进行code review,尽管我之前也有在互联网实习的经历,但这是第一次接触Gerrit,本着学什么都要有输出的想法,想写写文章记录下这一两周来的使用心得。
Gerrit基础概念
Gerrit是一个在线Code Review网站,让开发者push commit到网上让同事code review,其原理也不难理解,开发者push commit到一个由Gerrit进行管理的临时分支上,只有等到code review通过之后才会将该commit提交到原本想push到的分支上。
举个栗子,假设现在有一个commit1,原本要push到branch1,但是开发者不能直接push到branch1,他需要将commit1 push到一个名为refs/for/branch1的临时分支上,只有等到commit1 code review通过后,才会将commit1提交到branch1分支上。
以下操作都是基于Gerrit Demo项目来进行演示的。
clone操作
从Gerrit拉项目时,会提供两个选项。
- Clone with commit-msg hook
- Clone
个人建议最好选择clone with hook选项。
hook机制每次在你提交的时候都会自动生成一个Change—Id并附在commit message里。
按照Gerrit的规范,没有Change-Id的commit是一个不完整的commit,不允许提交。
因此,如果选择Clone方式,在push的时候就会报错ERROR: missing Change-Id in commit message
尽管也有补救措施,但为什么不一步到位呢?具体解决办法可参考Stack Overflow上这个回答。
commit操作
commit操作中比较需要注意的点是commit message,因为根据Gerrit要求,其必须符合模版要求才能提交。
每个公司都有自己的commit message模版要求,需要注意的是模版中如果有冒号,冒号:
后面是跟着一个空格的(血泪教训),其它的这里就不过多赘述。
可以在~/.gitmessage里配置好commit message模版要求,这样就可以避免每次都要手动输入模版。
push操作
push 操作主要有两种。
-
朴实无华的bash命令。
git push origin HEAD:refs/for/whatever_branch_name
-
使用AS进行push。
假设现在要push到master分支。
只需要将分支名修改为refs/for/master。
不过这个方法每次push时都需要手动对分支名进行修改,但我暂时没有想到更好的方法,有其它更好方法的读者欢迎在评论区留言。
添加reviewers
点击下图红框所在选项进行添加reviewers。
submit操作
代码在code review通过后,界面右上角会有一个submit
选项,点击它就能把修改提交到原本的分支上啦。
rebase
有时候待review的commit界面左上角会爆红,提示merge conflict,这时候只需要点击界面右上角的rebase选项一般就能解决这个问题,如果继续报错的话可见后面的内容。
特殊情况的处理方案
code review没通过
这种情况太常见了,特别是对于我这种刚入职的应届生来说,code review被revoked是家常便饭了。
有多种处理方式,下面列举3种。
-
线上修改。 如下图所示,界面右上角有一个edit选项,点进去后就能直接在线上进行修改。
修改完成后会有两个选项进行选择。
- save。该选项意思是保存该修改,但该修改只对自己可见。
- save&publish。该选项意思是保存并发布该修改,该修改对所有人都可见。
-
使用朴实无华的bash命令修改。
1.在terminal里输入下列命令把上一笔commit修改为modified且unstaged的状态。
git reset HEAD^
- 此时就可以对上一笔的提交的内容进行修改。
- 修改完后,再提交。 需要注意的是这种方式需要重新填写commit message。
-
AS修改。
在AS自带里的Git插件里点击想要修改的commit并右键选择Undo Commit。
后续步骤和方式2差不多,区别在于方式3会保留commit message。
-
git amend。
这种方式可以用Android Studio自带的图形界面完成,或使用命令行,下面只介绍第一种方式。
Android Studio自带的图形界面的方式只需要在提交修改的时候把下面红框勾选上即可。
个人比较推荐方式2,3,4,因为方式1线上修改存在以下弊端:
- 无语法提示。
- 无法测试修改后是否达到预期。
第一周我就遇到了这种情况,年轻不懂事,直接线上修改,顺利通过code review了,后来其它同事发现我这笔提交甚至无法编译成功。
Conflict无法通过线上Rebase解决的处理办法
以我个人为例,发生这种情况一般是发生在线上cherry-pick的时候,因此这里的处理方法以cherry-pick为例进行讲解,其它情况的处理办法也差不多。
处理方法有多种,说说我自己的处理方法,我自己会在线下用AS重复这个cherry-pick的操作,之后AS会报Conflict的错,处理完成Conflict后,我就会直接push到线上,这时候线上这笔提交就会显示Conflict已经成功处理。
优缺点
优点
代码更加规范。这是项目引入Gerrit的初衷,尽管我有多次Code Review没通过的情况,但确实是因为我的个人代码没有达到要求,而我也在这么多次Code Review没通过的情况下,逐渐对如何写出更符合规范的代码有了更深的理解。
缺点
流程更耗时。
把代码push上去,让同事帮忙code review一下,同事此刻不一定能抽出时间来帮你review,好不容易等到他可以review了,往往会发生下列情况:
- 如果他负责的代码和我不一样。我需要给同事解释我这么修改的意图是什么。
- 如果他觉着没问题了,code review通过了,又会发现由于等待时间过长,其它同事又有新的提交了,界面左上角会爆红提示说merge conflict了,
- 运气好的时候,只需要线上rebase一下然后等待系统重新触发code-check和ui-check通过后就能submit了。
- 运气不好的时候,需要线下处理冲突的时候,在线下处理冲突完成后还需要再让同事Code Review一次。
如果此时处于提测阶段,还需要把这笔提交cherry-pick到提测分支,再重新走一遍Code Review的流程。
为了缩短Code Review的流程耗时,我的策略是速战速决。
- 提交前先让同事喵一眼,免得Code Review不通过。
- 提交后立即口头跟同事说Code Review一下。
写在最后
上一篇文章是5个月前发布的,倒也不是我犯懒,不愿意写了,主要是这段时间在补计算机基础知识,例如计网和操作系统,这类知识有个特点是要点过多,不是一两篇文章能写完的,再加上临近大四毕业,各种琐事和饭局,遂没有继续写下去。
如今我毕业了,开始工作了,会重新开始写文章,如写写小组项目需要用到的偏应用层技术的文章。
还是一样,文章如果有错,欢迎指出。
peace。