基于邮件 Patch 的开发流程
Published:
大型开源项目一般都采用 Patch workflows, 记录一下个人配置开发环境的流程。
Linux 内核的开发便是如此, 也最容易通过相关的文档来入门。
参考资料
概述
整体来说,Patch 以邮件作为载体供社区中的大伙来审阅、讨论。
在 The Linux Kernel Mailing List (LKML) 中列出的就是最新的一些 Patch, 这个网页相当于是一个公共收件箱,每个发出来的 Patch 都会抄送 LKML, 所以负责审阅的人都能从这里拉取到 Patch (可以借助 b4 来实现很多方便的功能)
在实际开发过程中主要就是三个问题,
- 如何准备 Patch ?
- 如何发送 Patch ?
- 如何回复 Review 的意见?
准备 Patch
git 仓库中的 commit 可以用 git format-patch 的方式来生成 Patch, 如果直接只指定 commit 就会把指定的 commit(不包括这个commit)的到当前 HEAD 的 commit 都分别生成 Patch.
git format-patch [commit]
更常见的用法是指定 commit 的数量。如果指定了数量 <n>,那就是从指定的 commit 往前数 n 个 commit
git format-patch -n [commit]
这里的 commit 如果省略,那就是从当前 HEAD 开始往前数 n 个 commit. (包括当前HEAD) 我觉得这一般也是最常用的做法, 有多少个 commit 就指定多少个就好了。
开发过程中为了解决一个问题,可能需要不止一个 commit, 所以发邮件的时候不能单个 Patch 发送,需要组成一个 Patch series 再发送。这个时候会用到 --cover-letter 这个选项, 将多个 Patch 组成一个 Patch series, 并且有一个封面,用来总结这些 Patch 的目的。
用 git 发送 Patch series 的时候,实际上还是每个 Patch 一封邮件,并且封面是第一封邮件, 每个邮件都被称为一个 Message, 后面每个 Patch 按照提交的先后顺序依次回复这个封面的邮件.
不同的 Patch 版本,可以在 format-patch 的时候来指定
git format-patch -v<n>
大家对一个 Patch 或者 Patch series 的讨论 Message 会组成一个 Thread。 有一个常见的选项是 --in-reply-to,可以用它指定前一个版本的 Message-ID, 然后这个新的 Patch, 就可以追加到原来的 Thread 里。这样可以比较方便追踪历史。 但是这只适用于 Patch 中只有一个 commit 的情况,如果是 Patch series, 不推荐 用这个选项,因为这会让整个 Thread 变得很复杂。推荐只在封面里加上版本说明, 并附上前面几个版本在LKML上的链接。
发送 Patch
这个问题在 Learn to use email with git! 中有完整的解答。而且 git send-email 也可以完成 format-patch 的功能, 直接发送邮件,跳过产生 Patch 的过程,但我看了一下开发过程中一般还是推荐先把 Patch 生成出来,方便检查和存档,然后再发送 Patch。
我用的是 Gmail 邮箱,并且配置的是 OAuth2 认证, 所以还需要额外安装一些东西
pip install keyring requests keyring.alt
其中 keyring.alt 用于给 keyring 提供后端实现。后面就是按照 git-credential-email 仓库中的说明完成配置即可。
git credential-gmail --set-client
git credential-gmail --authenticate
然后再更新一下 git config 的配置就可以用 git send-email 来发送邮件了。
回复 Review 意见
回复 Review 意见时主要需要注意发送 Plain Text 的邮件。可以参考 Use plain text email
我一开始使用的 thunderbird, 但是我后来发现还是命令行好用,所以切换到了 neomutt + mbsync + msmtp
- mbsync 用来将 Gmail 邮箱中的邮件同步到本地
- msmtp 用来发送邮件
- neomutt 是一个邮件客户端,用看来查看和回复邮件
相关的配置我也都同步到我的 dotfile 里了。
主要是登陆 Gmail 邮箱时可以设置一个独立的 app 密码 Sign in with app passwords 然后用 pass 来管理。