时光荏苒,岁月如梭…… (?太文绉绉了,这不是我的风格)
今天我准备聊聊在 GitHub 上如何玩 Code Review。
突发奇想?心血来潮?不是。
咋回事呢?(对八卦不感兴趣的可以直接跳到下一节,但是我猜你会感兴趣。)
首先我是 DevStream 开源社区成员。
在五月份,又有3位活跃的优秀的牛X的 Contributors 正式加入 DevStream 开源社区,正式成为了社区 Member!
(看下面的红框框)

于是乎,加上三月份的4个“老 Member”,DevStream 社区就有7个“社区 Member”了(社区 Member 区分于像我这种在思码逸上班的内部 Member)!
7个疯狂输出的 Members,外加接近20个 Contributors,我和铁心两个人基本就只能看着 pr 笑笑,一边表示欣喜,一边表示 review 不过来了,“应接不暇”,废了废了……
也就是说,是时候组织一个 reviewer 组,拉着大家一起玩 Code Review 流程了!
说到 Code Review 流程,流程是啥?规范是啥?规则是啥?技巧是啥?xxxx?我能预想到 reviewers team 这个事情落地之日会有一堆问题砸到我头上。好吧,我需要写一篇文章来聊聊这些事。
下面我们开始一次 Code Review 之旅。
开始一次 review 之前,首先咱得“认领”一个 review 任务。
怎样算成功认领?如下图,Reviewers 里有你的头像,这时当前 pr 你就是 reviewers 之一,同时可以看到黄色 bar 里的一行字“This pull request is waiting on your review.”以及绿色的按钮“Add your review”。你可以点击这个“Add your review”开始一次 Code Review 之旅。

“那么怎么认领呢?” 可能你还想问我。
这个问题有答案,也没有答案。
因为你是 reviewer 之一,那么你就有权限自己点击 Reviewers 右边的⚙️齿轮按钮,然后指定自己是一个 Reviewer。如果你不是一个“合法”的 reviewer,那么你得先成为 reviewer (If you want)。
点击 Add your review 按钮后,咱就进入到了网页版 Code Review 页面,大致如下:

这里有很多值得“探索”的特性,比如:左边的“文件树”、文件树上方过滤“commits”的下拉框、右边的“文件过滤”、每个文件右上角的 Viewed 选择框、…… 每发现一个新功能,你的 review 过程就会多简化一分。
关于这个页面,没有比官方文档更权威和详细的介绍了,我想我没有理由“搬一次砖”,大家点击链接进一步探索吧。
对于简单的修改,或许网页直接查看代码 diff 就足够了,类似这种变更级别的 pr:

我们可以轻松判断这个修改是不是“正确”,然后选择进一步的操作,比如 Approve:

对于一个不能“一眼看穿”的 pr,比如对方没有附上详细的测试结果等信息来证明他的修改已经“充分测试”(充分测试的例子),这时候靠肉眼我们很难判断这个 pr 合入后会怎样,或者不借助 IDE 的能力我们甚至很难看懂一些复杂的修改,这时候就需要下载这个 pr 对应的代码到本地,然后用 IDE 来帮助 review 了。
以 pr #641为例,我们需要下载这个 pr,这时只需要执行这样两条命令:
git fetch upstream pull/641/head:pr641
git checkout pr641
效果如下:

然后在 IDE 里打开项目,就能看到 pr 对应的代码了:

“代码在手,天下我有!”
这会你可以在本地仔细查看每一处代码细节,可以在本地跑一下 make buid -j8 或 go test ./... 之类的命令来逐步“打消自己内心的疑虑”。当然,pr 本身会触发 GitHub actions workflows,这些基础的 build/ut 流程其实本地不跑也能知道是不是有错误,我们可以直接在页面上看到(每个项目具体的 ci 逻辑不一样):

到这里,你就基本能够完全看懂一个 pr 对应的所有修改了,是放他过?还是拦下马?他的“命运”掌握在你的手里!
可能有时候,你需要修改别人的 pr。哥们,我建议你抽根烟冷静一下,再问自己一句:我真的必须去修改他的 pr 吗?这样做会不会被打?
一般情况下,我不建议你去修改别人的 pr,尤其是不能保证你的修改一定正确的情况下。因为你别人的 pr 本身就是容易冒犯到别人的事情,其次万一你改了之后发现还需要别人自己补一个 commit,他会在复杂的 git 操作中骂你一万遍。
什么时候需要去动别人的 pr 呢?举个例子,比如这个 pr。
首先这是一个 new contributor 提交的 first pr,所以我不希望他的 first pr 之旅太艰辛。然后这个 feature 其实并不简单,虽然技术上看并不难,但是要做到“不重不漏”就需要对 dtm 命令的所有子命令都“了然于胸”才行。显然,这对一个 new contributor 来说要求太高了。所以在他提交了一个 commit 之后,我直接在这个 commit 的基础上又加了一个 commit,完成了剩下的工作,并且在认可他的工作后告知其为什么我要修改这个 pr,并附上了测试结果等。

具体怎么操作呢?步骤如下:
前面我们已经下载了一个别人的 pr 到本地,接着自然是继续修改,然后提交 commit(git add xxx & git commit -s -m "xxx"),到这里都没啥技术含量,不赘述了。
在 pr 页面可以看到具体 pr 是从哪里提交的,比如:

我们点进去,就可以找到 fork 项目的地址信息,像这样:

于是,我们可以这样来加一个 remote:
git remote add himku git@github.com:himku/devstream.git
此时这个 pr 对应的 fork 项目的地址是 himku(git@github.com:himku/devstream.git),对应分支是 fix-issue-559,于是我们可以这样将自己新增的 commit(s) 提交到这个 pr 里(本地 commit 后执行):
git push himku HEAD:fix-issue-559

是不是很酷?
再聊聊剩下的一些零零碎碎的问题,比如可能你想问 review 的目的啊,规范啊,要求啊,啊啊啊……
可能你会问我为什么要 code review ?我希望你别问。因为我不想总结。(这个问题可以 Google 到一堆答案)
我相信你心中有答案,code review 对应的是一堆的“褒义词”,比如:发现错误、保证质量、互相学习……
你想的都是对的,总之这个事情值得做就对了,不需要去总结为什么。
啥?
你还是想听我谈谈?
谈谈就谈谈。
当我们解决了所有“流程”或“技巧”层面的问题后,下一个“非技术性”问题是:怎样的代码需要“返工”?怎样的代码可以被合入?
我相信你心中会有这样的疑问。
对于有“错误”的代码,毫无疑问,不能合入,这不在我们的讨论范围。
那么正常运行,没有逻辑错误的代码呢?比如“代码风格有点混乱”,比如“缺乏必要的一些注释”,比如“可读性差”……
我们分三个层次来思考:

一般:如果一份代码功能完全正确,可读性也勉强还行,或许没有很好的面向对象来组织,或者注释不太详细,或者存在其他一些小小的不完美。这时候你也可以选择通过,避免太严格的 review 规则把一个 pr 的合入周期拖的太长,一方面影响交付效率,一方面打击开发者信心。很多时候我们可以对自己,或者对核心开发者要求更严格一些;但是对于社区贡献者,往往需要更多的“宽容”与认可。
温柔:如果是一个 new contributor 提交的一个 first pr,这时你可以放下各种能放下的要求,只要这份代码还过得去,就能合入,没有啥比给新人一些信心更重要的。如果 pr 存在一些小问题,你觉得对他来说改起来不会太困难,你可以留言友好的告诉他哪里需要改,怎么改;如果你觉得对他来说进一步做到“完美”有难度,你也可以直接提一个 fix 的 commit 到这个 pr 里,直接帮他修复问题,然后留个言告知他没有考虑到的问题是什么。
今天就聊到这里。
意犹未尽?
再去看看 Google 的 Code Review Developer Guide 吧!

如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195
我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong
我的Rails站点使用了一个确实不是很好的gem。每次我需要做一些新的事情时,我最终不得不花费与向实际Rails项目添加代码一样多的时间来为gem添加功能。但我不介意,我将我的Gemfile设置为指向我的gem的GitHub分支(我尝试提交PR,但维护者似乎已经下台)。问题是我真的没有找到一种合理的方法来测试我添加到gem的新东西。在railsc中测试它会特别好,但我能想到的唯一方法是a)更改~/.rvm/gems/.../foo。rb,这看起来不对或者b)升级版本,推送到Github,然后运行bundleup,这除了耗时之外显然是一场灾难,因为我不确定我所做的promise是否正
我们正在使用Vagrant进行部署,我们最终希望将此集群部署在Rackspace上。vagrant-rackspace插件是一个自然的选择,但它有一些错误,这些错误未包含在最新的0.1.1版本中(notablythatvagrantprovisiondoesn'twork)。我已经在我的personalfork中解决了这个问题通过合并其他人的工作来对存储库进行改造。是否可以从github安装vagrant插件?显而易见的事情没有奏效:[unix]$vagrantplugininstallvagrant-rackspace--plugin-sourcehttps://github.com
我一直在尝试使用nanoc用于生成静态网站。我需要组织一个复杂的排列页面,我想让我的内容保持干燥。包含或合并的概念在nanoc系统中如何运作?我已阅读文档,但似乎找不到我想要的内容。例如:我如何获取两个部分内容项并将它们合并到一个新的内容项中。在staticmatic您可以在您的页面中执行以下操作。=partial('partials/shared/navigation')类似的约定在nanoc中如何运作? 最佳答案 这里是nanoc的作者。在nanoc中,部分是布局。因此,您可以拥有layouts/partials/shared/
我有一个使用Jekyll托管在GitHub上的静态网站。问题是,我真的不需要master分支,因为存储库唯一包含的是网站。这样我就必须gitcheckoutgh-pages,然后gitmergemaster,然后gitpushorigingh-pages。有什么简单的方法可以摆脱gh-pages分支并直接从master推送? 最佳答案 Theproblemis,Idon'treallyneedthemasterbranch,astheonlythingtherepositorycontainsisthewebsite.Isthere