我有4台Ubuntu机器,Jenkins作业在它们上运行。一个共享磁盘作为/data/repositories/
安装到它们上。在它下面,有许多由git clone <url> --no-checkout -b master
创建的非裸存储库。
当作业被触发时,它会运行以下步骤:
- 在
/data/repositories/foo
中,获取Branch A
和Branch B
- 解析
Branch B
头并获取其提交SHA1VALUE
- 通过
git worktree add --no-checkout /path/to/worktree SHA1VALUE
创建工作树 - 在
Branch A
头中获取更改后的文件 - 在
/path/to/worktree
中启用稀疏签出 - 将更改后的文件写入
/data/repositories/foo/.git/worktrees/xx/info/sparse-checkout
- 在
/path/to/worktree
中运行git checkout
以签出这些文件 - 使用
git cherry-pick
将Branch A
头应用于/path/to/worktree
中的SHA1VALUE
- 将新提交推送到
Branch B
/path/to/worktree
不在共享磁盘上,而是在每台机器自己的磁盘上。在步骤7和步骤9中,它可能偶尔会引发错误fatal: not a git repository /data/repositories/foo/.git/worktrees/xx
。当错误发生时,/data/repositories/foo/.git/worktrees/xx
不在那里,就好像它在步骤之前被某个进程或线程删除了一样。在作业中,在作业完成或在这些步骤中引发异常之前,不会故意删除它。
如果使用相同的参数重新生成作业,则问题不会再次出现。
如果/data/repositories/foo/.git/worktrees/xx
一开始没有成功创建,那么它将在这些步骤中被检测到,并且步骤8总是失败。
多个作业可以同时在同一个/data/repositories/foo
上运行。但在/data/repositories/foo/.git/worktrees/xx/info/sparse-checkout
中,xx
部分是唯一的。
谢谢你提供任何线索。
感谢@torek。虽然还不清楚问题的确切原因,但我找到了解决方案。根据解决方案,正如@torek所指出的,根本原因很可能与种族条件和文件系统类型有关。
共享磁盘为NFS,非共享磁盘为EXT4。因此,主存储库位于NFS系统中,其工作树在EXT4系统中创建。在并发作业运行的某些未知条件下,主存储库中的工作树gitdir会被意外删除,当然工作树也会被禁用。
解决方案是在共享磁盘中创建工作树,以便主存储库和工作树位于同一磁盘上。测试大约8小时后,问题不会再次出现。