13

有两个我感兴趣的场景。

  • 存储库是共享的,两个用户希望同时向它推送更改
  • 我想使用 cron 作业安排每晚或每周的“gc”。它运行并且有人想在操作期间推送或克隆。

在这两种情况下是否存在腐败风险?

4

2 回答 2

12

Git 通过使用悲观并发控制来允许并发操作。

必要时,git 会创建一些特殊文件来充当锁。

特别是,每次操作修改索引时,git都会在目录中创建一个名为index.lock.git文件来锁定共享资源。Git 会根据需要创建其他锁定文件:例如,.keepgit index-pack操作期间创建文件。

通常,您不必担心 git 的并发操作:它经过精心设计以支持它们。

有人可能会告诉你不应该担心执行cron 作业,因为 git 本身会不时gc触发。gc即使这是真的,手册页本身也建议:

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,但是如果您的情况完全不同,我不会感到惊讶。

于 2015-04-26T08:13:08.893 回答
3

通常,“ git gc”可能会删除另一个并发进程正在使用但尚未创建引用的对象。
Git 2.12(2017 年第一季度)对此有更多的了解。

请参阅Matt McCutchen ( )的提交 f1350d0(2016 年 11 月 15 日) 。(由Junio C Hamano 合并——提交 979b82f中,2017 年 1 月 10 日)mattmccutchen
gitster

并查看Jeff King 的评论

现代版本的 git 做两件事来帮助解决这个问题:

  • 任何被“最近”对象(在 2 周内)引用的对象也被认为是最近的。因此,如果您创建一个指向树的新提交对象,即使在您引用该提交之前,该树也受到保护

  • 当由于我们已经拥有该对象而优化了对象写入时,git 将更新文件(松散对象或打包文件)上的 mtime 以刷新它

不过,这并不完美。您可以决定在删除现有对象时引用它。并且修剪过程本身不是原子的(而且要做到这一点很棘手,只是因为文件系统对我们的承诺)。

如果您有长时间运行的数据(例如,一个临时索引文件,它可能会存在数天或数周),我认为这是一个潜在的问题。解决方案可能是以某种方式使用 refs 来指向您的对象。
如果您担心某人碰巧同时运行的短期操作git-gc,我同意这可能是一个问题,但我怀疑您在实践中可以忽略一些问题。

对于繁忙的多用户服务器,我建议完全关闭 auto-gc,并使用 " -k" 手动重新打包以确保安全。

这就是为什么git gc手册页现在包括:

另一方面,当 ' git gc' 与另一个进程同时运行时,它可能会删除另一个进程正在使用但尚未创建引用的对象。如果其他进程稍后添加对已删除对象的引用,这可能只会导致其他进程失败或损坏存储库。

Git 有两个特性可以显着缓解这个问题:

  • 任何修改时间晚于--prune日期的对象,以及可从该日期访问的所有内容都将被保留。

  • 如果对象已经存在,大多数将对象添加到数据库的操作都会更新对象的修改时间,以便应用#1。

然而,这些功能还没有一个完整的解决方案,所以同时运行命令的用户不得不忍受一些损坏的风险(这在实践中似乎很低),除非他们使用 'git config gc.auto 0' 关闭自动垃圾收集.


请注意最后一句话,包括“除非他们关闭自动垃圾”:Git 2.22 (Q2 2019) 修改 gc 文档。

See commit 0044f77 , commit daecbf2 , commit 7384504 , commit 22d4e3b , commit 080a448 , commit 54d56f5 , commit d257e0f , commit b6a8d09 (07 Apr 2019), and commit fc559fb , commit cf9cd77 , commit b11e856 (22 Mar 2019) by Ævar Arnfjörð Bjarmason ( avar) .
(由Junio C Hamano 合并 -- gitster--提交 ac70c53中,2019 年 4 月 25 日)

gc文档:删除不正确的引用gc.auto=0

由于“”而导致存储库损坏的可能性gc与是否通过“”调用“gc”无关,而与是否gc --auto发生其他并发操作有关。

这已经在本段前面提到过,所以没有理由在这里提出这个建议。用户可以从文档的其余部分推断“ gc”将自动运行,除非gc.auto=0设置,我们不应该通过暗示“ gc --auto”比正常的“ gc”更容易产生损坏来混淆问题。

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

于 2017-01-15T17:55:08.693 回答