我的日常工作和开源工作经常要用到 git 和 GitHub ,所以我发现了有一些我经常用到的实用模式。
下文中我会把 pull 请求(pull request)简写成PR。
1. 剥离的PR
我什么时候用?
- 工作在特性开发分支
- 发现不好的代码想要马上就地修正,但是和我正在做的特性无关(例如一个小bug,或者哪里不一致,或者有违背代码规范)
我该做什么?
- 暂停当前的进度(通过提交commit或者暂存stash)
- 检出master分支
- 新建分支
- 修正代码,提交
- 切换回特性开发分支,继续工作
- 等特性开发分支合并(merge)到master分支后,再变基(rebase)到前面新建的分支上
这个既满足想要快速修正无关问题的愿望,又能保持特征开发分支的清晰明了,让评审变得更容易。
2. 乐观的分支
我什么时候用?
- 有一个暂不能合并(例如持续集成构建失败,代码评审者很忙等原因)的分支(分支A)
- 我需要基于分支A的代码做另一个改动
我该做什么?
- 在分支A上创建一个新的分支(分支B)
- 等分支A合并到master分支后,把分支B变基到master分支,并解决产生的任何冲突
- 这样在分支A上对bug的修正都变基到分支B上了
这种处理有冲突的风险,如果在分支A上做的改动特别大。但是这个乐观的策略95%的情况都工作良好。
3. 机智的PR
我什么时候用?
- 假设我做的修改事实上不需要评审
- 我还是需要我的队友知道这件事
我该做什么?
- 在分支上做修改
- 报一个PR
- 自己迅速合并这个PR
这个方法不会阻碍我的继续,但是GitHub还是会通过邮件通知我的队友这个PR。因此大家觉得有异议也都可以评论这个修改。
4. 偷偷摸摸的提交
我什么时候用?
- 代码评审过了,并且合并到了master
- 我需要做一个小改动(例如复制改动,或者bug修正),但是没必要通知别人
我该做什么?
- 只要把新的提交push到master
5. the roger roger 评论
我什么时候用?
- 从分支的代码评审那里收到了可操作的回馈
- 已经基于回馈做好了相应的修改
我该做什么?
* 评论包含了该修改提交的引用的PR
* GitHub会聪明地在差异链接处增加引用的次数,这样我的同事:
→ 得到修改的邮件通知
→ 简单地点击提交差异链接
→ 知道他们可以继续代码评审了
6. 慢慢爬的提交
我什么时候用?
- 发现自己引入了一个小小的格式化的bug(例如不必要的空格,文件最后没有换行等),或者
- 某逻辑代码修改实际上属于前一个提交, 或者
- 代码不可提交(例如某些测试未成功)但是我还是想要回退到这个状态,这样我可以安全地测试
我该怎么做?
- 前两种情况,我会补救amend前一次提交
- 第三种情况,我有一个正在开发的(爬行的)提交,我渐进地进行补救(或者如果实验失败那就回退)直到我的代码可以真正提交了。
7. 强制修改的分支
我什么时候用?
- 我需要补救一个远端功能开发分支,例如提交信息里的说明非常糟糕
我该做什么?
- 在本地补救提交
- 把该功能开发分支强制推送到远端的版本库
强制推送到远端分支应该是 git 的一个禁忌,但是我的经验是这样处理很少有问题(只要它是普通分支,不是master就行)。GitHub 能很好地处理强制推送到PR分支,例如不会丢失前一次的提交的评论。
8. 重新格式化剥离
我什么时候用?
- 我想修改同时格式化代码
我该做什么?
- 在master上做一个仅包含重新格式化部分的提交
- 把我分支变基到master
这种方法,让分支的差异在代码评审者眼里变得更加清晰明了,因为它不包含格式化
9. 原型PR
我什么时候用?
- 想要让我的点子在写大量实现代码前得到大家的反馈
我该做什么?
- 在某个分支上做点整理
- 为此报一个PR,目的不是要发布最终代码,而是作为大家讨论的出发点
- 当达成一致开始下一步时关闭该PR(并且删除分支)
- 新建另外一个分支和PR,这次好好写代码
我以前习惯于当代码完成时应该报一个PR。现在我真正领悟到了为什么“pull request是一个开始讨论的好办法” —— GitHub的围绕PR的功能(例如内联评论、回复、通知和比较差异)对于促进代码和设计讨论堪称卓越,还可以防止开发者偏离正题太远,跑到死胡同。