有两个我感兴趣的场景。
- 存储库是共享的,两个用户希望同时向它推送更改
- 我想使用 cron 作业安排每晚或每周的“gc”。它运行并且有人想在操作期间推送或克隆。
在这两种情况下是否存在腐败风险?
有两个我感兴趣的场景。
在这两种情况下是否存在腐败风险?
Git 通过使用悲观并发控制来允许并发操作。
必要时,git 会创建一些特殊文件来充当锁。
特别是,每次操作修改索引时,git都会在目录中创建一个名为index.lock
的.git
文件来锁定共享资源。Git 会根据需要创建其他锁定文件:例如,.keep
在git 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
,但是如果您的情况完全不同,我不会感到惊讶。
通常,“ 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
服务器上的并发“”可能会导致损坏。