Git的锁定策略如何实现并发?

10

最近我一直在阅读关于如何设置Git服务器的内容,发现根本不需要特定的守护程序(只需要一个带有文件系统的SSH服务器),我开始更深入地了解Git在底层是如何管理文件的。

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

尽管如此,在某些情况下,并发无法得到保证,这基本上是当历史记录被重写(强制推送)时。此时,是否存在在树中使用锁定策略来避免并发问题?是否有更多关于此主题的文档资料?

(在这个SO答案中提到了一些关于此主题的内容,但很简略。)

2个回答

12

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

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

非常聪明和简洁。


谢谢!有关垃圾回收如何工作的任何参考资料吗?因为我认为那是一个本地工作副本操作,而不是客户端可以在服务器上执行的操作。 - knocte

4

为了充当锁定的作用,需要创建各种文件。Git会创建一个名为.git/index.lock的文件来锁定索引。git index-pack可以创建一个.keep文件以防止竞争条件。可能还有其他例子。


1
值得一提的是,index.lock 是用于 Git 索引的,因此仅用于提交,即仅在本地存储库中使用,通常由单个用户使用。对于推送到远程存储库,无需使用索引。index-pack 通常在 git gc 过程中使用。 - kan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接