所以我最近一直在阅读如何设置git服务器,并且发现根本不需要特定的守护进程(只有一个带有文件系统的SSH服务器),我开始更多地了解git管理文件。
每个提交如何在.objects文件夹中表示以及所有内容如何组合在一起的策略非常巧妙,但似乎没有明确提到这种方法实际上使git以非常简单的方式实现并发而没有需要信令服务器。
尽管如此,在某些情况下无法保证并发性,这基本上是在重写历史记录(强制推送)时。在这种情况下,树中是否使用了任何锁定策略来避免并发问题?那里有关于这个主题的更多文档吗?
(this SO answer中有关于此主题的内容,但只是非常简短。)
答案 0 :(得分:11)
git数据结构是不可变的,除了refs(即分支/标签/等),“重写历史”不是非常正确的术语,更合适的“创建替代历史”。回购将拥有所有对象 - 新旧对象。此外,在“推送”对象期间在本地存储库中创建的所有更改都只是传输。然后你推它,它首先发送所有对象(因为对象是由它的内容定义的,它们是唯一的,没有并发问题)。发送所有对象后,引用正在更改。它只是一个小的单个文件(refs/heads/<branchName>
)来覆盖40个字节的sha1键。据我所知,它确实对文件进行了原子比较和设置更改。它读取旧的ref值,创建一个锁定文件,检查旧值是否未更改,替换为新的sha1并删除锁定。如果失败,则推送失败,您需要重试(即乐观锁定)。您可以从source code,update_ref函数中找出更多详细信息。
强制推送后,可能会出现一些“松散的对象”(即未从任何现有引用中引用的对象),因此这些对象将在以后进行垃圾收集。
非常聪明又整洁。
答案 1 :(得分:4)
在必要时创建各种文件以充当锁。 Git创建一个名为.git/index.lock
的文件来锁定索引。 git index-pack
可以创建.keep
文件以防止竞争条件。可能会有更多的例子。