我有一段时间很在意提交记录的数字。
打开仓库,先看绿色的方块,再点开一条 commit。数字往上走的时候,会有一种事情没有白做的错觉:今天留下了一条记录,明天再留一条,某个阶段就被证明存在过。可提交记录只是一个计数器,它能告诉我做过多少次保存,却不能替我解释这些保存为什么发生。
后来我开始重新看那些旧仓库。它们并不整齐,也没有一条漂亮的成长曲线。早期的代码会把界面、数据和事件处理揉在同一个文件里,函数名常常只够让当时的自己看懂;文档只写了“怎么运行”,没有写“为什么这样做”。有些仓库很久没有再打开,另一些却在隔了很久之后又出现了修补。
这些缺口并不丢人。它们只是说明代码曾经处在一个具体的时间里。人往往要先把东西做出来,等下一次遇到同样的问题,才知道上一次哪里留下了债。
三个小仓库
BookManager 是一个用 Python 和 PyQt5 写的图书信息管理系统,仓库带有 MIT 许可证,最早的提交在 2023 年 12 月,后来又有一轮文档和小修补。它没有被包装成什么大型系统,项目目录里能看到窗口、表单和数据操作各自留下的痕迹。现在回头看,我更在意它让我第一次必须面对的那个问题:“界面上的一个动作到底会改动什么数据?”
wps_script 是一组放在金山文档 AirScript 环境中运行的日常任务。仓库同样以 MIT 许可证发布,最近的公开提交集中在任务适配和表格验证上。它和课堂作业不太一样:代码不是写完就结束,外部接口变了,原本能工作的任务就会沉默。维护它需要先确认输入、输出和模拟测试能证明什么,再决定哪些变化值得写进脚本。很多时候,所谓“修好了”只意味着契约测试重新通过,并不等于真实账号已经验证完毕。
bosszhipin_spider 的公开说明把它描述为 Python 与 Pyppeteer 组成的招聘数据采集工具,仓库有 MIT 许可证,也保留了爬虫与数据合并测试。这个项目让我对“能抓到数据”和“应该怎样使用数据”之间的距离更敏感。代码可以公开,测试可以公开,真实职位数据、个人信息和站点规则却不能因为出现在一个仓库里就被随意搬走。留下代码,不等于留下所有上下文的授权。
这三个仓库没有共同的技术栈,也没有组成什么宏大的产品线。它们只是分别记录了界面、接口适配和数据处理的几个阶段。把它们放在一起看,反而能看到一条更可靠的线:从“让页面动起来”,到“让任务在变化中继续工作”,再到“先问数据是否应该被处理”。
旧代码没有替我成长
有时我会把仓库更新误认成成长。只要最近还有 commit,就好像自己仍然在前进;很久没有提交,就像某段时间被从履历里删掉了。可代码不会因为被推送到远端就自动变得成熟。一个仓库也不会因为拥有更多星标就替我承担维护责任。
真正留下来的,是一些更细小的判断:把一次重复的修补写成测试,把外部接口的假设记在文档里,把不能公开的数据挡在仓库之外,在没有必要时不再增加一个功能。它们没有明显的仪式感,甚至很少出现在项目介绍里,却比一个好看的数字更接近工程经验。
我现在打开旧仓库,先看的不再是提交总数,而是三个问题。这个项目当时想解决的具体麻烦是什么?哪些地方只在我的电脑上成立?如果今天交给另一个人,他能不能从文档和测试里判断边界?答案往往不够漂亮,但至少可以继续往下做。
让痕迹保留原来的重量
代码和照片有一点相似。照片能证明某个瞬间被按下快门,却不能自动说明当时的人在想什么;提交能证明文件被保存过,却不能替我补写当时的动机。若要把旧项目写成文章,最容易犯的错就是给它加上一条顺滑的故事线,把零散的修补说成早已规划好的路线。
我不想再这样处理自己的记录。能从公开仓库核对的,就写仓库实际呈现的内容;没有证据的数字和场景,就删掉;涉及他人和第三方数据的部分,宁可留在原处。文章可以有情绪,但情绪不能替事实增加一条提交记录。
这些项目以后也许还会被打开,也许会一直停在某个旧版本。它们不会替我证明已经成为怎样的人,只会安静地告诉我:在某些具体的下午,我曾经把问题拆开,试着让下一次运行少一点意外。
这就够了。痕迹不是计数器,也不是一份需要不断美化的成绩单。它只是让过去保持可核对,让后来的人,包括未来的我,知道一段代码从哪里来,又在哪些地方需要重新开始。