在 Windows VM 和 Linux 主机之间共享 Git 存储库
Share Git repository between Windows VM and Linux host
我主要在 Linux 上工作,但我也有一个 Windows 虚拟机,主要用于 Windows 上的 运行 单元测试。
在 Linux 中,我有一个 Git 存储库,可以使用 VirtualBox 共享文件夹从 Windows VM 访问它。我不在 Windows 上使用 Git,除了我们的构建系统,它记录当前的 Git 哈希以将其包含在可执行文件中(运行ning git describe --always --dirty
).
现在,每次我在 Linux 或 Windows 上使用 Git 然后在另一个系统上再次使用时,都需要一段时间。例如:
Linux$ git status
Linux$ git status # fast (<1s)
Windows$ git status # takes a few dozen seconds
Windows$ git status # fast (<1s)
Linux$ git status # takes a few seconds
Linux$ git status # fast (<1s)
我能做些什么来防止这种情况发生吗?我最好关闭 Windows 上的 Git 功能,因为它只需要获取哈希值。但是我无法更改此哈希的获取方式,因为这在构建系统中很深。我也不希望在 Linux 和 Windows 和 commit/push 上有单独的存储库,因为这会导致更大的开销。
Linux git 版本:2.11.0.
Windows git 版本:2.14.1.windows.1.
您在这里看到的是 Git 的索引在用作 缓存 时的有效性。
连同它所做的所有其他事情,Git 的索引充当有关 work-tree 的数据缓存,以加速文件系统操作——好吧,真的,到 跳过 文件系统操作,如果可能的话。它通过记录有关文件(以及秘密的目录,即使 Git 实际上并不存储目录)的统计信息来实现这一点。此缓存仅在满足多个条件时才有效。如果不是,Git 必须在 work-tree 上执行昂贵的文件系统操作,如您所见,在 Linux 上确实需要 秒 的时间, 在 Windows.
上甚至更慢
共享文件夹违反了缓存假设。特别是,索引中的一项是 work-tree 的 path,并且 Linux 系统中的路径与 Linux 中的路径不同 Windows虚拟机。 (无论两个系统的托管方式如何,这通常都是正确的。)
有几种明显的方法可以解决这个问题:
- 不要分享 work-tree。这可能是最好的方法。
- 不允许其中一个系统更新索引(通过 read-only 更新索引——这可能有点棘手)。
- 在其中一个系统上使用单独的索引:默认索引是
$GIT_DIR/index
,其中 $GIT_DIR
来自环境或默认来自 git rev-parse --git-dir
,但设置 GIT_INDEX_FILE
到路径名将覆盖它。
我建议方法 1 的原因是它内置于 Git,如果您的 Git 至少是 2.5 版,则使用 git worktree add
。注意每个 Git work-tree 必须在自己的分支中,或者使用分离的 HEAD;分离的 HEAD 方法可能适用于此目的,只需在那里使用 git checkout --detach <branch>
进行更新。
我主要在 Linux 上工作,但我也有一个 Windows 虚拟机,主要用于 Windows 上的 运行 单元测试。
在 Linux 中,我有一个 Git 存储库,可以使用 VirtualBox 共享文件夹从 Windows VM 访问它。我不在 Windows 上使用 Git,除了我们的构建系统,它记录当前的 Git 哈希以将其包含在可执行文件中(运行ning git describe --always --dirty
).
现在,每次我在 Linux 或 Windows 上使用 Git 然后在另一个系统上再次使用时,都需要一段时间。例如:
Linux$ git status
Linux$ git status # fast (<1s)
Windows$ git status # takes a few dozen seconds
Windows$ git status # fast (<1s)
Linux$ git status # takes a few seconds
Linux$ git status # fast (<1s)
我能做些什么来防止这种情况发生吗?我最好关闭 Windows 上的 Git 功能,因为它只需要获取哈希值。但是我无法更改此哈希的获取方式,因为这在构建系统中很深。我也不希望在 Linux 和 Windows 和 commit/push 上有单独的存储库,因为这会导致更大的开销。
Linux git 版本:2.11.0.
Windows git 版本:2.14.1.windows.1.
您在这里看到的是 Git 的索引在用作 缓存 时的有效性。
连同它所做的所有其他事情,Git 的索引充当有关 work-tree 的数据缓存,以加速文件系统操作——好吧,真的,到 跳过 文件系统操作,如果可能的话。它通过记录有关文件(以及秘密的目录,即使 Git 实际上并不存储目录)的统计信息来实现这一点。此缓存仅在满足多个条件时才有效。如果不是,Git 必须在 work-tree 上执行昂贵的文件系统操作,如您所见,在 Linux 上确实需要 秒 的时间, 在 Windows.
上甚至更慢共享文件夹违反了缓存假设。特别是,索引中的一项是 work-tree 的 path,并且 Linux 系统中的路径与 Linux 中的路径不同 Windows虚拟机。 (无论两个系统的托管方式如何,这通常都是正确的。)
有几种明显的方法可以解决这个问题:
- 不要分享 work-tree。这可能是最好的方法。
- 不允许其中一个系统更新索引(通过 read-only 更新索引——这可能有点棘手)。
- 在其中一个系统上使用单独的索引:默认索引是
$GIT_DIR/index
,其中$GIT_DIR
来自环境或默认来自git rev-parse --git-dir
,但设置GIT_INDEX_FILE
到路径名将覆盖它。
我建议方法 1 的原因是它内置于 Git,如果您的 Git 至少是 2.5 版,则使用 git worktree add
。注意每个 Git work-tree 必须在自己的分支中,或者使用分离的 HEAD;分离的 HEAD 方法可能适用于此目的,只需在那里使用 git checkout --detach <branch>
进行更新。