Who Should Pay For Source Code Availability?

Who Should Pay For Source Code Availability?

谁该为源代码的可用性买单?

Loris Cro Personal Website About • Blog • Twitch • YouTube • GitHub / Codeberg Who Should Pay For Source Code Availability? August 09, 2026 • 30 min read • by Loris Cro

Loris Cro 个人网站 关于 • 博客 • Twitch • YouTube • GitHub / Codeberg 谁该为源代码的可用性买单?2026年8月9日 • 30分钟阅读 • 作者:Loris Cro

The story of how I became Radicle-ized. I have a project (Zine, a static site generator) that has 11 dependencies hosted across GitHub, Codeberg, and self-hosted Forgejo instances. Whenever GitHub or Codeberg is down, fresh builds of my project will fail.

这是我如何被“Radicle化”的故事。我有一个项目(Zine,一个静态网站生成器),它有11个依赖项,分别托管在 GitHub、Codeberg 和自托管的 Forgejo 实例上。每当 GitHub 或 Codeberg 宕机时,我项目的全新构建就会失败。

While self-hosted Forgejo instances have significantly better uptime than GitHub, they are at greater risk of eventually going down for good and breaking my project permanently.

虽然自托管的 Forgejo 实例的正常运行时间明显优于 GitHub,但它们面临着最终永久下线并导致我的项目彻底崩溃的更大风险。

The most direct and practical solution to this problem is to fork/vendor everything. Forking means moving all dependencies to the same host where Zine is. If you can clone the main project, you will also be able to clone all its dependencies.

解决这个问题最直接、最实际的方法是 fork(派生)或 vendor(供应商化/本地化)所有内容。Fork 意味着将所有依赖项移动到与 Zine 相同的托管平台上。如果你能克隆主项目,你也就能够克隆它所有的依赖项。

Vendoring means taking it one step further: you commit all your dependencies’ source code into your own repo so the act of cloning the project gets you literally everything. If practicality and maximum resilience are things you care a lot about, then you might prefer vendoring over forking.

Vendoring 意味着更进一步:你将所有依赖项的源代码提交到你自己的仓库中,这样克隆项目时就能获得所有东西。如果你非常看重实用性和最大程度的韧性,那么你可能更倾向于选择 vendoring 而非 forking。

Forking requires you to fork your entire dependency tree (i.e. your indirect dependencies as well), and also modify any non-leaf dependency to point at your own forks. Vendoring instead is extremely straightforward for users of the Zig toolchain.

Forking 要求你派生整个依赖树(即包括间接依赖项),并修改任何非叶子依赖项以指向你自己的 fork。相比之下,对于 Zig 工具链的用户来说,Vendoring 非常简单直接。

For those who are not in the know, Zig 0.17.0-dev recently changed how dependency caching works: the global cache now stores packages as compressed archives, and each project has a local zig-pkg/ directory that contains the extracted files of the dependencies used by it. This makes vendoring trivial if that’s your goal: just check your zig-pkg/ directory into source control. (Otherwise, it’s recommended to add it to .gitignore.)

对于那些不知情的人,Zig 0.17.0-dev 最近改变了依赖缓存的工作方式:全局缓存现在将包存储为压缩归档文件,每个项目都有一个本地的 zig-pkg/ 目录,其中包含该项目所用依赖项的解压文件。如果你的目标是 vendoring,这让操作变得微不足道:只需将 zig-pkg/ 目录提交到版本控制中即可。(否则,建议将其添加到 .gitignore 中。)

If you plan to make changes to your dependencies and care about making it easier to upstream them, then forking might be preferable to vendoring. Even if you don’t plan to send a pull request, it’s much easier to cherry-pick a commit in a fork than to do so from a vendored directory in an external project.

如果你计划修改依赖项,并且希望更轻松地将更改合并回上游,那么 forking 可能比 vendoring 更合适。即使你不打算发送拉取请求(Pull Request),在 fork 中 cherry-pick 一个提交也比从外部项目的 vendored 目录中操作要容易得多。

Forking/vendoring works, there’s no doubt there. But is it really the best we can do? Languages that have a centralized package index (like npmjs.com or crates.io) don’t have to worry about these issues because they essentially have the forking strategy as a built-in feature (all source code gets ‘forked’ into a copy hosted by the centralized package index), but this approach really leaves me unsatisfied because it unnecessarily ties the solution to package management. Our aim should be to make source code reliably available always, not just when fetched from a package manager.

Forking/vendoring 确实有效,这一点毋庸置疑。但这真的是我们能做到的最好方案吗?拥有集中式包索引(如 npmjs.com 或 crates.io)的语言不必担心这些问题,因为它们本质上将 forking 策略作为内置功能(所有源代码都被“fork”并托管在集中式包索引的副本中)。但这种方法让我很不满意,因为它不必要地将解决方案与包管理绑定在一起。我们的目标应该是让源代码始终可靠可用,而不仅仅是在通过包管理器获取时才可用。

These topics have become more relevant as of late because of the instability of GitHub, but in reality the question is not “how can we make source code hosting reliable?”. We do know how to make code hosting reliable, if we really want to. The question is rather: how much should it cost, and who should pay for it?

由于 GitHub 的不稳定,这些话题最近变得更加重要,但实际上问题不在于“我们如何让源代码托管变得可靠?”。如果我们真的想,我们确实知道如何让代码托管变得可靠。问题在于:这需要多少成本,以及谁应该为此买单?

As is often the case in our industry, we never wanted to face that question, and we’ve been happy to leech off big tech companies but, as always, eventually an answer to the question must be given and, when that happens, we’re quick to point the finger at the company, yelling “enshittification!” with righteous indignation.

正如我们行业中常见的情况,我们从不想面对这个问题,我们一直乐于从大型科技公司那里“白嫖”。但一如既往,这个问题最终必须得到回答。而当那一刻来临时,我们又会迅速指责这些公司,义愤填膺地大喊“垃圾化(enshittification)!”。

And yeah, GitHub is without a doubt enshittifying, same as Discord and many other platforms before them; but for how long do we expect to continue consuming resources for free? The situation with GitHub is just showing us the cracks in a system that was always broken to begin with.

是的,GitHub 毫无疑问正在“垃圾化”,就像之前的 Discord 和许多其他平台一样;但我们还指望免费消耗资源多久?GitHub 的现状只是向我们展示了一个从一开始就破碎的系统中的裂痕。

I don’t think that companies are without blame, and I’m sure that obfuscating the cost equation has its own dedicated chapter in plenty of unwritten playbooks, but it’s not the companies that should know better. It’s us. It’s our willful ignorance that creates a distortion that companies have to either embrace or exploit to be competitive.

我不认为公司没有责任,我也确信在许多不成文的商业手册中,掩盖成本等式都有专门的章节。但应该更清醒的不是公司,而是我们。正是我们的刻意无知造成了一种扭曲,而公司为了保持竞争力,要么必须接受这种扭曲,要么必须利用它。

So, is there a way to make source code reliably available in a way that balances out the cost equation? I would argue that self-hosting a forge is not enough to balance the equation because it puts the entire cost of making source code available onto the creator of said software, but we already established that consumers of such code also have an interest in it being reliably available, which is what leads to forking and vendoring.

那么,有没有一种方法可以既让源代码可靠可用,又能平衡成本等式呢?我认为仅靠自托管代码仓库不足以平衡这个等式,因为它将使源代码可用的全部成本都压在了软件创作者身上。但我们已经确定,代码的使用者同样有让代码可靠可用的需求,这正是导致 forking 和 vendoring 的原因。

Forking and vendoring are in a sense a way of sharing the cost to keep source code available, but they’re both inefficient because forked/vendored code is not trivially discoverable and automatically usable as a mirror.

从某种意义上说,forking 和 vendoring 是一种分摊保持源代码可用性成本的方式,但它们效率都很低,因为 fork/vendor 后的代码无法被轻易发现,也无法自动作为镜像使用。

If somebody is interested in one of your dependencies outside the context of your project, their package manager won’t be able to automatically fetch it from your forked/vendored copy. Of course you might not be interested in shouldering this cost but, as things stand, that’s not really an option anyway. It would be cool if we could do better, because that could help us lower the overall cost of keeping source code reliably available for everybody.

如果有人在你的项目之外对你的某个依赖项感兴趣,他们的包管理器将无法自动从你 fork/vendor 的副本中获取它。当然,你可能不想承担这个成本,但就目前的情况来看,这其实没得选。如果我们能做得更好会很棒,因为这有助于降低让所有人都能可靠获取源代码的总体成本。

The Radicle Network: Radicle is a peer to peer (p2p) network where peers seed repositories that they’re interested in.

Radicle 网络:Radicle 是一个点对点(p2p)网络,节点(peers)可以在其中为他们感兴趣的仓库提供种子(seed)。

Some seeds might be interested in making the network more resilient and thus will want to reseed everything (or close to), while others might be interested in making sure that a specific set of projects is guaranteed to be available, restricting their seeding policy to allowing related repositories exclusively.

一些节点可能热衷于增强网络的韧性,因此愿意为所有(或大部分)内容提供种子;而另一些节点可能只关心确保特定的一组项目始终可用,从而将其种子策略限制为仅允许相关的仓库。

Radicle supports Issues and Patches (aka Pull Requests in GitHub lingo) in a very interesting manner: there is no centralized (nor federated) web server that hosts those, because they are stored in the Git repository itself as (CRDT-enabled) Git objects that can be re-synced when you announce your changes to the network (run git push in concrete terms).

Radicle 以一种非常有趣的方式支持 Issues 和 Patches(GitHub 术语中的 Pull Requests):没有集中式(或联邦式)的 Web 服务器来托管这些内容,因为它们作为(支持 CRDT 的)Git 对象直接存储在 Git 仓库本身中。当你向网络宣布你的更改时(具体来说就是运行 git push),这些对象可以被重新同步。

To help you better understand how this feature works, let’s focus on Issues using a concrete example. Let’s say that I’m interested in using Radicle for…

为了让你更好地理解此功能的工作原理,让我们以 Issues 为例进行具体说明。假设我有兴趣在……中使用 Radicle。