10

所以我最近一直在阅读有关如何设置 git 服务器的内容,并且在发现根本不需要特定的守护进程(只是一个带有文件系统的 SSH 服务器)后,我开始更多地研究 git 如何管理文件引擎盖。

每个提交如何在 .objects 文件夹中表示以及所有内容如何组合在一起的策略非常聪明,但似乎没有明确提到这种方法实际上使 git 以非常简单的方式实现并发,而不需要信令服务器。

尽管如此,在某些情况下无法保证并发性,这基本上是在重写历史时(强制推送)。在这种情况下,树中是否使用了任何锁定策略来避免并发问题?那里有关于这个主题的更多文档吗?

(在这个 SO 答案中对这个主题说了一些话,但只是非常简短。)

4

2 回答 2

12

git数据结构是不可变的,除了refs(即分支/标签/等),“重写历史”不是很正确的术语,更适合“创建替代历史”。回购将包含所有对象 - 新的和旧的。此外,在“推送”对象期间在本地存储库中创建的所有更改都只是传输。然后你推送它,它首先发送所有对象(因为对象是由它的内容定义的,所以它们是唯一的,不存在并发问题)。发送完所有对象后,引用正在发生变化。它只是一个很小的单个文件(refs/heads/<branchName>) 用 40 字节的 sha1 键覆盖。据我所知,它会对文件进行原子比较和设置更改。它读取旧的 ref 值,创建一个锁文件,检查旧值是否不变,用新的 sha1 替换并删除锁。如果失败,则推送失败,需要重试(即乐观锁)。您可以从源代码update_ref 函数中了解更多详细信息。

在强制推送之后,可能会出现一些“松散的对象”(即没有从任何现有 ref 引用的对象),因此这些对象稍后会被垃圾收集。

非常聪明和整洁。

于 2013-11-13T21:09:59.933 回答
4

在需要充当锁的地方创建了各种文件。Git 创建一个名为.git/index.lock锁定索引的文件。git index-pack可以创建一个.keep文件来防止竞争条件。可能还有更多的例子。

于 2013-11-13T19:38:48.017 回答