Worktree & PR
一个 worktree 能带来两样东西:任务运行期间主工作副本保持可用,未改动的副本可作为基线进行对比。这两点都值得付出真实的搭建成本,但并非适用于每一次改动。
本文覆盖隔离机制本身。改动本身应该多大属于 scoped-change 的范畴,它在 worktree 内部的应用方式与其他地方完全一致。
判断是否使用
当至少满足以下一条时,考虑使用 worktree:任务足够大,半完成状态会阻塞其他工作;多个任务需要同时在同一仓库上推进;结果需要与当前行为进行对比;或者改动风险足够高,放弃它应当不产生任何成本。
当改动很小、自包含、一次审查即可完成时,跳过它。为修正一个拼写错误或一行配置编辑而搭建隔离副本,成本高于收益,而且额外的分支、目录和 PR 都是日后需要有人承担的负担。当请求方明确要求在當前分支上直接工作时,这个决定已经做出。
运行
从集成分支拉出分支,而不是从当前检出的内容拉出。隔离副本的意义在于干净的起始状态;继承无关的进行中改动会丧失这一点,并使最终的 diff 难以阅读。先 fetch,使基线是当前的,而不是过期的本地引用。
任务运行期间不要动主工作副本。同时编辑两者会破坏隔离并毁掉基线。如果任务最终需要在主工作树中做改动,停下来说明,而不是伸手过去改。
并行 worktree 只有在彼此不相交时才能保持独立。同一仓库的两个副本编辑相同文件,会汇聚成没人安排过的冲突,而成本会在合并时而非现在显现。在打开第二个之前,先检查第一个正在触碰什么。
明确指定产物的存放位置。在 worktree 内生成的截图、构建产物和导出文件会随它一起消失。请求方需要看到的任何内容都必须写到持久位置,或附加到 PR 上,并且必须说明位置,而不是假定。
宣布完成之前
与未改动的基线对比,而不是与预期对比。保留干净副本的理由就是运行两者并观察差异。对于行为变更,这意味着走一遍旧路径和新路径;对于视觉变更,这意味着同一视图捕获两次。“应该等价”是一个断言,而基线就在那里可供核对。
说明工具链额外添加了什么。生成输出、格式化器改动和依赖锁更新会在隔离副本中累积,而没有人主动选择它们,一旦合并就与有意改动无法区分。要么解释每一项为何属于这个分支,要么丢弃它。
落地
遵循用户既定的授权偏好。如果提交、推送或创建 pull request 需要明确授权,先完成并验证本地改动,然后交出确切的命令,直到获得授权。获得授权后,推送分支并创建 pull request,描述动机、执行过的命令以及审查者必须手工检查的内容;除非另有指示,合并留给仓库所有者。明确说明哪些部分已完成、哪些未验证、哪些被有意省略,因为 worktree 的隔离很容易让人把未测试的结果报告为已完成。分支落地后,移除 worktree;已合并分支的陈旧副本是下一个打开它的会话的陷阱。