Git存储库是否支持并发操作?

14

我感兴趣的有两种情况。

  • 仓库是共享的,两个用户想同时推送更改
  • 我想使用cron作业安排每夜或每周运行"gc"。在操作期间,某人想要推送或克隆。

这两种情况中是否存在损坏的风险?


对于#1,我假设您正在谈论并发推送到不同的分支?关于同时推送到同一分支的问题已在SO的其他地方得到回答。 - cmbuckley
2
q8424232; q6028141 也许也很有趣。 - cmbuckley
2个回答

12
Git使用悲观并发控制允许并发操作。
必要时,git会创建一些特殊文件作为锁。
特别是每次索引被操作修改时,git都会在.git目录中创建一个名为index.lock的文件来锁定共享资源。Git在需要时创建其他锁定文件:例如,在git index-pack操作期间会创建一个.keep文件。
通常情况下,您不必担心git的并发操作:它经过精心设计以支持它们。
有人可能会告诉您不用担心使用cron作业执行gc,因为git本身会定期触发gc。即使这是真的,man page本身也建议:
Users are encouraged to run this task on a regular basis 
within each repository to maintain good disk space utilization
and good operating performance.

因此,我认为将任务计划安排为运行git的垃圾回收并不是一个坏主意。我只是想知道这是否为过早优化或您正在解决实际的、可衡量的问题。个人而言,我从未遇到需要手动运行gc的问题,但如果您的情况非常不同,我也不会感到惊讶。

4

"git gc" 通常会删除正在使用,但尚未创建引用的对象,即使其他并发进程正在使用该对象。
Git 2.12 (2017年第一季度) 对此进行了更多解释。

参见 commit f1350d0(由 Matt McCutchen (mattmccutchen) 于 2016年11月15日提交)
(由 Junio C Hamano -- gitster -- 合并于 commit 979b82f,2017年1月10日)

并查看Jeff King的评论

现代版本的git有两个功能来帮助解决这个问题:
  • 任何被“最近”对象(在2周内)引用的对象也被认为是最近的。因此,如果您创建了一个指向树的新提交对象,即使在引用该提交之前,该树也会受到保护。
  • 当我们已经拥有该对象时,优化掉对象写入时,git会更新文件(松散对象或packfile)上的mtime以进行刷新。
然而,这并不完美。您可能会在正在删除其内容的同时决定引用现有对象。修剪过程本身也不是原子的(由于文件系统所承诺的东西,使它变得棘手)。如果您有长时间运行的数据(例如,可能会在几天或几周内实际存在的临时索引文件),我认为这是一个潜在的问题。解决方案可能是以某种方式使用refs来指向您的对象。 如果您担心短期操作,例如某人恰好与您同时运行git-gc,则我同意这是一个可能的问题,但我认为您可以忽略它。对于繁忙的多用户服务器,我建议完全关闭自动gc,并手动使用“-k”重新打包以确保安全。
这就是为什么git gc手册页面现在包括:
另一方面,当`git gc`与另一个进程同时运行时,存在它删除另一个进程正在使用但尚未创建引用的对象的风险。这可能只会导致另一个进程失败,或者如果另一个进程稍后添加对已删除对象的引用,则可能破坏存储库。Git有两个功能可显着减轻此问题:任何修改时间晚于`--prune`日期的对象都将保留,并且包括从该对象可达的所有内容;大多数向数据库添加对象的操作会更新对象的修改时间(如果该对象已存在),以便应用第1点。但是,这些功能还不足以解决完全的问题,因此,除非使用者关闭自动垃圾回收(使用“git config gc.auto 0”),否则并发运行命令的用户必须承担一定的损坏风险(在实践中似乎很低)。
关于最后一句话包括“除非他们关闭自动垃圾回收”的说明:Git 2.22(2019年第二季度)修订了gc文档。

请查看以下提交记录:commit 0044f77commit daecbf2commit 7384504commit 22d4e3bcommit 080a448commit 54d56f5commit d257e0fcommit b6a8d09(2019年4月7日),以及commit fc559fbcommit cf9cd77commit b11e856(2019年3月22日),作者为Ævar Arnfjörð Bjarmason (avar)
(由Junio C Hamano -- gitster --commit ac70c53合并,2019年4月25日)

gc 文档: 删除关于 gc.auto=0 的错误引用

由于 "gc" 导致存储库损坏的机会与是否通过 "gc --auto" 调用 "gc" 没有任何关系,而是取决于是否有其他并发操作正在进行。

这已经在段落中早先注意到了,因此没有理由在这里建议。用户可以从文档的其余部分推断出除非设置了 gc.auto=0,否则 "gc" 将自动运行,我们不应该暗示 "gc --auto" 比普通的 "gc" 更容易产生损坏。

嗯,从某种意义上说,阻塞的 "gc" 会阻止您在特定的终端窗口中执行任何其他操作,但用户可能会拥有另一个窗口,或者担心服务器上的并发 "gc" 可能会导致损坏。


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