软件维护之文档与版本控制:维护文档撰写、Git分支策略、变更管理
说实话,干逆向和软件维护这么多年,我见过太多项目死在「文档缺失」和「版本混乱」这两件事上。代码写得再漂亮,没有文档就是一堆废铁;版本控制搞得稀烂,改个bug能改出三个新bug。今天咱们就聊聊这块硬骨头——怎么把文档写明白,怎么把Git分支管清楚,怎么把变更控制住。
维护文档撰写:别让后来人骂你
我刚开始做逆向的时候,最怕的就是打开一个项目,发现里面只有代码,连个README都没有。你想想看,一个几万行的C++项目,没有注释、没有设计文档、没有变更记录,那简直就是考古现场。后来我自己带团队,定了一条死规矩:没有文档的代码,不允许合入主分支。
文档到底写什么?
我个人习惯把维护文档分成三类,每一类都有明确的产出物:
| 文档类型 | 核心内容 | 谁来看 |
|---|---|---|
| 架构设计文档 | 模块划分、接口定义、数据流、依赖关系 | 新入职的工程师、维护人员 |
| 变更日志(CHANGELOG) | 每个版本的变更点、修复的bug、已知问题 | 测试人员、项目经理、下游开发者 |
| 操作手册 | 环境搭建、编译步骤、部署流程、常见问题 | 运维人员、实施工程师 |
嗯,这里要注意——架构文档不是让你把代码抄一遍。我见过有人把整个类的成员函数列表贴进去,那叫「代码转述」,不叫文档。真正的架构文档,要回答的是「为什么这么设计」而不是「怎么实现的」。
文档的版本管理
文档和代码一样,也要做版本管理。我建议把文档和代码放在同一个仓库里,用同样的分支策略。为什么?因为文档和代码是绑定的——v1.0的代码对应v1.0的文档,v2.0的代码对应v2.0的文档。分开管理,迟早会乱套。
我曾经在一个项目里吃过这个亏。文档单独放在一个Wiki里,代码在Git上。结果代码改了三个版本,Wiki还是最初的版本。新来的同事照着Wiki搭环境,折腾了两天没跑起来,最后发现是文档没更新。从那以后,我坚持文档必须和代码同仓库、同分支、同标签。
Git分支策略:别让你的仓库变成毛线球
分支策略这东西,说白了就是「怎么管住大家的手」。没有策略的Git仓库,你打开一看,几十个分支乱七八糟,有的分支已经三个月没动过了,有的分支和主分支差了200个commit。嗯,这种仓库我见过太多了。
我常用的分支模型
我个人比较推荐的是「Git Flow」的简化版,适合中小团队。核心就几个分支:
- main(主分支):只放稳定版本,每次合入必须经过Code Review和测试
- develop(开发分支):日常开发的主战场,功能分支从这里拉出去,合回来
- feature/xxx(功能分支):每个新功能一个分支,开发完成后合入develop
- hotfix/xxx(热修复分支):线上出bug了,从main拉出来修,修完合回main和develop
- release/x.x.x(发布分支):准备发布时从develop拉出来,只修bug不加功能
你可能会问:「功能分支要不要保留?」我的建议是:功能合入develop之后,直接删掉。留着只会增加混乱。Git又不是不能找回,真需要了去reflog里翻就行。
分支命名规范
分支命名这件事,看起来是小事,但做不好真的很头疼。我见过有人用「fix-bug」、「new-feature」这种名字,过两周自己都忘了是干什么的。我建议统一格式:
feature/【需求编号】-【简短描述】
hotfix/【bug编号】-【简短描述】
release/【版本号】
举个例子:feature/REQ-1234-user-login-optimization。一看就知道是哪个需求、干什么用的。别嫌名字长,长名字比看不懂的名字好一万倍。
变更管理:改代码不是请客吃饭
变更管理,说白了就是「怎么控制谁在什么时候改了什么东西」。没有变更管理的项目,就像没有交通信号灯的路口——早晚得出事。
变更的流程
我一般要求团队走这么几步:
- 提Issue:任何变更,先提一个Issue,描述清楚「为什么要改」「改什么」「影响范围」
- 拉分支:从develop拉出功能分支,命名按上面的规范
- 写代码+写文档:改代码的同时,更新对应的文档和CHANGELOG
- 提Pull Request:代码写完了,提PR,指定Reviewer
- Code Review:至少一个人Review通过才能合入
- 合入+打标签:合入develop,如果是发布版本,再合入main并打tag
变更日志怎么写?
CHANGELOG这个东西,很多人觉得是形式主义。但真正出问题的时候,你就知道它有多重要了。我举个例子:线上出了个bug,你怀疑是某个版本引入的。如果没有CHANGELOG,你得一个一个commit去翻;如果有CHANGELOG,看一眼就知道是哪个版本改了相关代码。
我习惯用「Keep a Changelog」的格式,按版本号倒序排列:
# Changelog
## [2.1.0] - 2024-03-15
### Added
- 新增用户登录日志记录功能
- 新增API限流机制
### Fixed
- 修复了内存泄漏问题(Issue #234)
- 修复了并发场景下的数据竞争(Issue #238)
### Changed
- 优化了数据库连接池配置,性能提升约30%
## [2.0.1] - 2024-02-28
### Fixed
- 紧急修复了登录接口的SQL注入漏洞(CVE-2024-XXXXX)
嗯,这里要注意——CHANGELOG是写给「人」看的,不是写给机器看的。别把commit message直接贴进去,要提炼成别人能看懂的语言。
SVG流程图:文档与版本控制的核心逻辑
下面这张图是我自己总结的「维护文档与版本控制」的核心流程。你看一眼,基本就能明白整个体系是怎么运转的:
你看这张图,三个模块是相互支撑的。文档告诉你「代码是什么」,分支策略告诉你「代码怎么管」,变更管理告诉你「代码怎么改」。缺了任何一个,另外两个都玩不转。
避坑指南:我踩过的那些坑
最后分享几个我亲身踩过的坑,希望能帮你少走弯路:
- 我曾经以为文档可以后补——结果项目赶进度,代码写完了,文档永远「下周补」。最后项目交付了,文档还是空的。现在我的原则是:文档和代码同步写,哪怕晚一天都不行。
- 我曾经在main上直接修bug——修完发现忘了合回develop,结果develop上还留着那个bug。下次发布的时候,bug又出来了。嗯,从那以后我再也不直接改main了。
- 我曾经用「final」、「最终版」这种名字命名分支——结果第二天又改了一版,变成了「最终版2」。现在想想真是哭笑不得。分支名一定要有意义,别偷懒。
好了,关于文档和版本控制,今天就聊到这儿。这些东西看起来都是「基本功」,但真正做好的团队真不多。你想想看,如果你的项目文档清晰、分支整洁、变更可控,那维护起来得多省心?