如何临时锁定Git存储库?
首先,我知道我的问题已经被问到了,并且被认为是Git滥用(例如,请参阅)。我将尝试解释我的用例 我需要定期(cron作业)对存储库中的源版本进行特殊的长时间处理。为了不干扰回购,我提取了所需的版本。不幸的是,Git中没有类似于导出的东西。文档建议使用如何临时锁定Git存储库?,git,locking,export,git-checkout,Git,Locking,Export,Git Checkout,首先,我知道我的问题已经被问到了,并且被认为是Git滥用(例如,请参阅)。我将尝试解释我的用例 我需要定期(cron作业)对存储库中的源版本进行特殊的长时间处理。为了不干扰回购,我提取了所需的版本。不幸的是,Git中没有类似于导出的东西。文档建议使用存档。因为我想要一个源目录树的精确副本(如工作目录中所示),所以我必须在某个目标位置解压归档文件 事实上,这看起来确实像一个签出,但是签出也会更改索引,这会导致用户对意外更改感到意外 许多答案建议在这种情况下克隆repo,然后在克隆上无害地播放。我不
存档
。因为我想要一个源目录树的精确副本(如工作目录中所示),所以我必须在某个目标位置解压归档文件
事实上,这看起来确实像一个签出
,但是签出
也会更改索引,这会导致用户对意外更改感到意外
许多答案建议在这种情况下克隆
repo,然后在克隆上无害地播放。我不想继续这样做,因为我必须同时提取多个版本,而且我不想为每个副本浪费repo存储空间(比如像Linux内核这样的monster repo)
我也不想使用worktree
,因为我的副本将被严重调整,我不想承担从这些精美副本提交回回购协议的风险。副本一经制作,Git就必须将其遗忘
我最终实现了一个export
等效的短脚本:
ref=$(git rev-parse --symbolic-full-name HEAD)
git --work-tree=<somewhere> checkout -f -q <branch_or_tag> -- '*'
git reset ${ref}
ref=$(git rev parse——符号全名头)
git--work tree=checkout-f-q--'*'
git重置${ref}
第一行保存repo中的当前位置(提交id)。第二行签出所需的版本而不更改头
,但同时将索引设置为签出提交。第三行恢复初始位置
这对裸存储库很有效,因为您不应该在那里提交commit
,而只能推送push
或pull
。除了创建一个索引文件之外,repo显然没有受到干扰
但是,如果脚本是针对本地存储库(具有关联的工作目录)运行的,则在其生命周期内存在一个小风险<代码>签出尽管快速不是瞬时的。索引将更改,直到重置完成。如果在此时间范围内尝试任何提交,则repo将因错误修补程序而受损,因为索引不是用户期望的
因此,我再次问@schuess的问题(见上面的链接):
有没有办法锁定Git存储库以阻止任何访问?
锁会很短。它应该防止存储库中的任何状态更改
现在我没有生活,但总有一天我会被抓住;因此,我更倾向于警惕这种比赛状态
提醒:我很清楚我在试图捉弄Git的背,我不应该这样做。更好的解决方案当然是实现真正的导出
脚本,而不依赖签出
。另请参见上文“为什么我不使用克隆”
这个答案分为两部分
如何得到你想要的
[使用]git--worktree=checkout-f-q
在裸存储库中运行良好
对。有一两条警告:
除了创建一个索引文件之外,repo显然没有受到干扰
事实上,这并不一定会创造它。可能已经有索引了。如果有索引,它将使用现有索引优化签出。这可以是好的也可以是坏的
具体来说,这是一些人在部署脚本中使用的技术:推送到裸存储库会触发一个Git钩子,它使用Git checkout
来更新部署分支。使用--work tree
将工作树作为常量字符串提供。索引跟踪该工作树的内容,而不跟踪其他工作树
有一种很好的方法来处理这个问题,它与git worktree使用的方法相同:为每个工作树分配一个索引。那个特定的索引然后只跟踪那个特定的工作树。与任何索引一样,您可以完全删除它,让Git稍后(如果有)重新构建它,只要您不介意丢失迄今为止存储在其中的任何更改
您可以创建自己的索引,方法是创建一个唯一的路径(例如,mktemp
),并将该路径设置到环境GIT_index_文件
,如中所述
[编辑:我已经删除了第二个警告,因为我看到您正在使用非头-更新git签出的表单:git签出--
]
为什么(可能)这些都不重要
你提到:
因为我想要一个源目录树的精确副本(如工作目录中所示),所以我必须在某个目标位置解压归档文件
与直接执行git签出相比,这项工作的成本非常低,至少在任何现代系统上都是如此:git归档…|tar-C path-xf-
可能比git checkout使用的CPU多一点,但还是要花费所有时间等待磁盘I/O。(管道使用内存中的“I/O”,因此以内存速度而不是I/O设备速度运行。)git archive
除了增加一点开销之外,唯一能做的就是遵守任何特殊的归档规则。这些特殊规则是使用git-archive
的优势,当然这些特殊规则也是使用git-archive
的劣势
许多答案建议在这种情况下克隆回购协议,然后在克隆上无害地播放。我不想继续这样做,因为我必须同时提取多个版本,而且我不想为每个副本浪费repo存储空间(比如像Linux内核这样的monster repo)
本地克隆(使用路径名或使用--local
)使用硬链接,因此不会增加额外空间。这只母鹿