跳转至

架构

如果你想做一个“能长期维护”的 Git 复现项目,第一件事不是狂写命令,而是先把结构拆清楚。

为什么 Git 复现项目很容易写乱

Git 类系统会同时碰这些东西:

  • 二进制对象格式;
  • Index V2;
  • refs;
  • 工作区改写;
  • merge;
  • pack;
  • 远端同步;
  • 危险文件操作。

如果一开始不拆边界,很容易演变成:

  • CLI 里直接写对象编码;
  • checkout 里重复实现路径保护;
  • merge 里自己读 refs、自己读 index、自己改工作区;
  • 每个命令都有一份不一样的删除逻辑。

这样一旦出 bug,很难知道错在底层数据结构、仓库状态机还是命令编排。

这个项目推荐的模块边界

python-git-reproduction 采用的思路大体是:

  • repository 负责仓库发现和上下文;
  • objects 负责对象编码、解码和校验;
  • index 负责 Index V2;
  • refs 负责 HEAD、branch、tag、remote refs;
  • lockfile 负责原子写入保护;
  • working_tree 负责磁盘文件层面的扫描与改写;
  • diff 负责状态比较;
  • merge 负责 LCA 与三方合并;
  • pack 负责 pack / idx;
  • remote 负责远端同步;
  • commands 负责对外命令编排。

为什么这种拆法合理

因为它让依赖方向变清楚:

  • 底层格式模块不需要知道 CLI 参数长什么样;
  • 高层命令层可以组合多个基础模块;
  • 危险逻辑可以集中复用;
  • 测试能更准确地定位问题。

比如:

  • 对象损坏问题应该优先在 objects 层测;
  • index checksum 问题应该优先在 index 层测;
  • merge 冲突问题应该优先在 merge 层测;
  • checkout 行为问题则属于高层编排层。

这和 SOLID / DRY 的关系

项目要求遵循 SOLID 和 DRY。
放到架构上,最直接的体现就是:

  • 单一职责要清楚;
  • 重复逻辑要集中;
  • 危险操作要统一保护;
  • 高层不要反向污染底层格式模块。

这不是空话。对 Git 复现项目来说,架构设计直接影响:

  • 是否容易误删文件;
  • 是否容易写坏 index;
  • 是否容易在多个命令里出现不一致行为。