无 Git 历史服务的源码基线恢复
一套服务还有当前源码,但没有可接续的 Git 历史。接手时首先需要确定后续改动基于哪一份文件,否则修复写完了,也很难说明改动前是什么状态。
2026 年 10 月 8 日,这次恢复建立了当前源码快照,纳入范围的 11 个文件与 SOURCE_IMPORT 中记录的哈希一致。本文根据当日记录整理,项目和部署信息已匿名化;恢复范围不包括插件和历史工具,当天也没有重新部署服务。
把恢复目标落到当前源码上
没有可用提交历史时,先把目标定为“保存这个时点拿到的源码,并留下校验依据”,任务会清楚很多。旧版本由谁修改、哪次发布引入了某个行为,都需要原有提交、备份或其他独立证据,当前目录本身回答不了这些问题。
Git 的术语说明把提交描述为包含文件状态及父提交等信息的对象。拿到一批源码再登记快照,可以给之后的工作建立起点,却不能据此补出过去的父提交关系、分支、作者和提交说明。
这次留下的是当前源码基线。以后再修一个函数,就有明确的前后对照;如果要恢复更早的版本,仍需要另找来源。导入快照的时间也只是登记时间,不能拿来推断文件最初写于哪一天。
先确认范围,再谈完整性
恢复清单比目录大小更有用。一个服务目录可能混放代码、运行数据、缓存、日志和旧备份;只看“拷贝完成”或文件总数,无法知道保存的是哪一类内容。
这次可确认的是:恢复范围中的 11 个文件有对应的哈希记录,复核结果一致。插件和历史工具没有纳入这个范围,因此后续维护不能默认它们已经在快照里。
遇到类似交接,我会先把来源说明写清楚,再开始修改。至少应记录捕获时间、纳入的相对路径、校验方法和排除项。如果只保存了源码,也要直接写明数据库、上传文件和运行状态是否另外备份,不能用一份源码清单代替整个服务的恢复说明。
这里的范围说明与哈希清单互相补充:范围说明回答准备保留什么,哈希回答这些文件在复制前后是否一致。清单里没有列出的文件,不会因为校验成功就自动得到覆盖。
哈希一致证明了什么
文件哈希适合检查内容传输和保存是否发生变化。相比文件大小或修改时间,逐文件摘要能更直接地发现内容差异。但前提是用于对照的清单有可信来源,并且确实对应准备恢复的那个捕获时点。
下面是采用 GNU sha256sum 的只读复核示例,文件名与清单是演示约定,不是本次 SOURCE_IMPORT 的原文或原始格式。假设已经有一份可信的 source.sha256,在捕获副本的根目录执行:
sha256sum --check --strict source.sha256sha256sum 手册说明,--check 会读取清单并核对对应文件,--strict 会让格式异常的清单导致失败。复核时需要检查命令退出状态,也要处理缺失文件和摘要不匹配,不能只从输出里挑几行成功结果。
这类校验只覆盖文件内容。权限、软链接目标、目录结构和清单是否完整,还需要单独记录;把所有文件都校验通过,也不能证明代码逻辑正确或服务可以启动。如果捕获期间源文件仍在变化,还需要一个一致的捕获窗口,否则可能得到来自不同时间的文件组合。
因此,这次“11 个文件哈希一致”的验收结论是:保存的文件与对应导入记录一致。它没有附带功能测试或业务数据恢复的结论。
原样保存与后续整理分开做
拿到旧源码后,很容易顺手格式化、改目录或替换配置。这些整理可能都有必要,但如果发生在基线确认之前,之后就很难区分哪些内容来自原文件,哪些内容是在交接时新改的。
更合适的顺序是先保留可校验的捕获副本,确认来源和范围,再把重构、依赖升级或配置调整作为后续变更。这样 review 能看到具体差异,遇到问题也能返回保存过的源码状态。
Git 本身也可能影响字节对照。gitattributes 文档说明,文本行尾、编码和过滤器可以在入库或检出时转换内容。原始副本与仓库检出文件的哈希不同,未必就是复制失败,需要检查是否发生了这些转换。要求按字节保留时,应保留原始捕获副本,并明确仓库采用的转换规则。
这也决定了来源说明的写法:只记录已经完成的动作,不把准备做的整理写成恢复结果。当前源码有哪些缺口,可以继续补;来源、时间和历史关系没有证据时,应保持未知。
源码恢复完成,部署另行验收
源码快照能让维护工作继续,但它不能单独承担生产回滚。服务重新运行还依赖运行时版本、系统库、启动方式、权限、当前配置和外部系统状态。特别是授权配置可能已经更新,旧源码副本里附带的配置不能直接覆盖仍在工作的环境。
后续如果需要重新部署,应先在隔离环境确认这些依赖,再安排维护窗口和独立验收。源码、配置与数据的回退方案也要分别确认:切回某个代码快照,不会自动撤销数据库变化,也不会恢复已经失效的外部授权。
本次工作停在可核对的当前源码基线,没有重新部署,也没有覆盖线上状态。11 个文件的导入校验提供了继续开发的起点;插件、历史工具以及更早的源码历史,仍需要独立补齐。