锁定git的策略实现并发?

时间:2013-11-13 18:53:23

标签: git concurrency git-push git-filter-branch

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

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

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

this SO answer中有关于此主题的内容,但只是非常简短。)

2 个答案:

答案 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文件以防止竞争条件。可能会有更多的例子。