把上游更新合并进你的 fork,最怕「顺序错了、接口断了、改漏了」。 这套方案用一张文件依赖图,在合并的每个环节做出更稳的决策—— 跨多种语言、结果可复现、所有增强都能按需开关。
不谈底层实现,先看它在一次真实合并里替你把住的几道关。
让被很多文件依赖的「基础文件」先合并,避免合到一半时因为依赖还没到位而构建失败。
在改动「被大量引用」的代码前提醒:保留对外接口,别让下游一片飘红。
上游改了某个接口,自动找出那些还在用旧用法、却忘了一起更新的文件。
审查大文件时,只展开真正相关的代码片段(含被外部引用的公共符号),省时也省成本。
需要人来定夺时,决策卡直接告诉你「这文件牵一发动多少」,判断更快更稳。
Python / JavaScript / TypeScript / Go 通用;所有增强默认安全,可一键开关。
两个最关键的概念:依赖图本身,以及它「只增不减风险」的安全守则。
节点是文件,边表示「A 引用 / 继承 / 调用 B」。 它不分析整个仓库,只聚焦本次改动文件及其邻居,构建成本可控,并随合并进度自动保存、断点续跑。
db.py 被很多文件依赖 = 枢纽文件(God Node),改它影响面最大、最该谨慎。
每条边都带一个可信度标签。核心守则:依赖图只会提高谨慎度, 绝不因为「图里没找到关系」就放松风险——宁可多审,不可漏审。点下面切换看每一档怎么用:
整套方案的核心设计:依赖图只在开始时构建一次,之后作为一份只读的共享资产, 被合并流程里 7 个不同环节各取所需。一处构建、多处复用,互不干扰。点任一环节看它怎么用图:
支撑上面这些能力的四组关键技术,以及为什么这样设计。
下面两个演示跑的是和系统里同款的真实算法逻辑,不是录像——点一点就懂。
每个文件先各成一组,每轮「随大流」——把自己的归属改成邻居里最多见的那一组。 互相引用密集的文件会自然聚到一起。点「下一轮」看它如何收敛成清晰的模块:
收敛后每组按成员的所在目录取个好认的名字。整个过程确定可复现;没有依赖边时则退回按目录分组——安全降级。
现代项目大量用别名或裸路径 import(比如 @app/util)。 不解析的话,这些其实是内部依赖的关系就被当成第三方丢掉了。选一条 import,看它如何被还原成仓库里的真实文件:
这些原则让一套「通用」的合并工具敢于引入依赖图,而不必担心拖慢或锁死在某一个项目上。
图为空、配置缺失、解析失败、解析器没装——统统回退到原有行为,绝不报错。最多少一点增益,绝不多一个问题。
模块划分、别名解析等增强默认关闭。不开启时,行为与没有依赖图时完全一致,保持对任意项目通用。
模块划分用标准库实现的「标签传播」,而非引入庞大的图计算库;别名解析也只用内置能力。体积小、好理解。
排序、聚类、解析全部确定——同样的输入永远得到同样的结果,支持断点续跑,不会两次跑出不同的计划。
| 能力 | 采用的技术 |
|---|---|
| 多语言依赖提取 | tree-sitter(JS/TS/Go)+ Python 内置 AST,缺失自动降级 |
| 合并定序 | 依赖图拓扑排序,作为同风险内的次级排序键 |
| 枢纽识别 | 影响半径(传递依赖计数)+ 可配置阈值 |
| 模块划分 | 标准库实现的标签传播,非重型图库 |
| 别名解析 | tsconfig 路径 / go.mod 模块 / 工作区包名 |
| 持久化 | 随合并 checkpoint 自动保存与恢复 |