如何临时锁定Git存储库?

如何临时锁定Git存储库?,git,locking,export,git-checkout,Git,Locking,Export,Git Checkout,首先,我知道我的问题已经被问到了,并且被认为是Git滥用(例如,请参阅)。我将尝试解释我的用例 我需要定期(cron作业)对存储库中的源版本进行特殊的长时间处理。为了不干扰回购,我提取了所需的版本。不幸的是,Git中没有类似于导出的东西。文档建议使用存档。因为我想要一个源目录树的精确副本(如工作目录中所示),所以我必须在某个目标位置解压归档文件 事实上,这看起来确实像一个签出,但是签出也会更改索引,这会导致用户对意外更改感到意外 许多答案建议在这种情况下克隆repo,然后在克隆上无害地播放。我不

首先,我知道我的问题已经被问到了,并且被认为是Git滥用(例如,请参阅)。我将尝试解释我的用例

我需要定期(cron作业)对存储库中的源版本进行特殊的长时间处理。为了不干扰回购,我提取了所需的版本。不幸的是,Git中没有类似于导出的东西。文档建议使用
存档
。因为我想要一个源目录树的精确副本(如工作目录中所示),所以我必须在某个目标位置解压归档文件

事实上,这看起来确实像一个
签出
,但是
签出
也会更改索引,这会导致用户对意外更改感到意外

许多答案建议在这种情况下
克隆
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
)使用硬链接,因此不会增加额外空间。这只母鹿