版本控制:分叉存储库如何在源代码托管设施上工作?

Version Control: How does forking a repository work on source code hosting facilities?

我有点好奇 Bitbucket、GitHub 和 Launchpad 等源代码托管工具如何实际管理来自主存储库的分叉过程,以及它们如何设法保存服务器磁盘 space 当这些存储库在服务器端分叉时。

例如,如果我从 GitHub 上的存储库中分叉:我的存储库中复制的代码是否从主存储库中占用额外的磁盘 space(我的意思是它会导致存储重复)在 GitHub 服务器上?

提前致谢。

这是一个很好的问题,让我想知道同样的事情。

Gitlab

幸运的是,有一个名为 gitlab 的开源 git 回购管理工具,我们可以看看。

gitlab-shell 中,fork_project 函数处理分叉。检查传递的参数是否有效后,执行以下行:

cmd = %W(git clone --bare -- #{full_path} #{full_destination_path})
system(*cmd) && self.class.create_hooks(full_destination_path)

因此 GitLab 只是克隆存储库,复制源代码。

相关问题

  • Are git forks actually git clones?
  • What is the difference between Forking and Cloning on GitHub?

根据 this answer 看来 GitHub 至少在分叉时不会复制存储库。相反,它会创建带有用户名前缀的新分支(例如,我的分支主分支将被引用为 lightcc.master,而不是 master)。

这在 Git 如何存储和引用文件以及为什么它能够如此有效地存储回购的上下文中非常有意义。如果 fork 是 repo 的完美副本,那么需要做的就是创建新分支(跟踪引用)并跟踪谁有权查看它们和 push/pull to/from。如果我 fork 一个 repo,但从未对其进行更改,那么我的跟踪引用可能落后于上游 repo,但它们将始终与那些旧提交相同(除非原始 repo 做了一些非常糟糕的事情 [tm] 和通过对现有提交进行变基、压缩等重写它的历史。

换句话说,在原始分叉时,需要复制 none 个原始 repo,因此唯一的成本是制作新跟踪引用所需的字节,即 ~40每个现有分支的字节数。它甚至可能无法创建新的引用,直到您真正偏离原始回购协议(或者直到您设置跟踪引用并将其推送到给定分支的分支 - 所以可能 master 是自动的?)。

鉴于评论,这似乎是 GitHub 所做的,因此 GitLab 实际复制 repo 的行为(根据 0xcaff 的回答)更类似于 Unix 分支,其中创建了重复的进程。 GitHub 以一种非常敏捷的方式,希望等到最后一刻才创建任何新对象,因为分叉实际上与原始存储库不同。

这可能就是为什么 GitHub 有一些关于将分叉与原始回购完全分离的规则,以及为什么需要参与支持。这样做会耗费他们的存储空间 space,如果他们让每个人都轻松且免费地这样做,随着时间的推移,他们可能会耗费大量存储空间 space 等。