git-工作树和共享存储库之间的区别?

时间:2019-01-29 19:42:40

标签: git

git worktree命令与通过使用--shared开关多次克隆本地存储库之间有什么区别?

我的目标是只将一个相对较大的存储库克隆到开发人员的计算机磁盘一次,并使用该存储库在多个分支上进行开发。我们不能使用git工作树,因为我们使用Eclipse和Eclipse does not support worktrees at the moment

我尝试过的并且似乎起作用的是以下内容:

  1. 从GitLab克隆存储库一次:git clone ssh://host/repo.git repository-master
  2. 再次克隆它而不将任何内容检出为共享存储库。这只会在第一个存储库中创建一些对打包文件的参考文件,而不会浪费任何磁盘空间: git clone --shared repository-master/ repository-branch1/
  3. 将GitLab存储库添加为共享存储库repository-branch1的远程目录:git remote add gitlab ssh://host/repo.git
  4. 获取数据git fetch
  5. 在第二个克隆repository-branch1中将所需的分支检出到新的本地分支:git checkout -b branch1 gitlab/branch1

这似乎可以解决所有问题:

  1. 有多个分支同时签出。
  2. 您可以将提交推送到两个分支。
  3. 您可以将项目导入Eclipse,并且Eclipse将识别该存储库。
  4. 磁盘上只有一个克隆的存储库。

我在这里错过了什么吗?当然,除了方便之外,肯定还有其他原因需要使用worktree命令吗?

2 个答案:

答案 0 :(得分:1)

使用--shared(或某些基于路径名的克隆隐含的--shared)的克隆是一个单独的存储库。通过使用硬链接 1 (操作系统必须支持),您将获得节省磁盘空间的全部好处, 2 具有绝对的安全性,因为Git不会覆盖任何现有的数据,它只会添加新数据,或者在相对罕见的情况下,取消链接文件,这现在是无害的,因为这只会减少使用该文件的Git存储库的数量。

git worktree add制成的工作树不是 一个单独的存储库。您在该工作树中 执行的所有操作,到您不在该工作树中 的任何分支或标签的所有其他工作树都会立即看到共享存储库。工作树具有其自己的HEAD(通常附加到分支名称,但可以选择是分离的),它自己的索引,当然还有它自己的工作树。几乎所有其他内容都是共享的(还有其他一些神奇的私有引用,例如git bisect,但例如,所有存储都在工作树之间共享)。

您现有的流程很好;请注意,磁盘空间共享最终将按照脚注2中的说明进行降级。


1 与某些基础文件对象建立硬链接会添加一个新名称,并增加链接数。链接计数始终代表文件的名称数量。上述取消链接操作是名称删除,而不是文件删除;仅当最后一个引用消失时,文件本身才会消失。

2 随着时间的推移,这种节省的性能会降低。这两个单独的存储库最初共享所有基础存储,但随后在某个时候,一个存储库决定打包松散对象或重新打包现有包,从而断开某些链接。实际上,另一个存储库现在拥有自己的私有副本。最终,所有链接可能都已断开,因此每个存储库都是真正独立的。存储库继续工作,但是不再节省空间。

答案 1 :(得分:0)

我认为您没有丢失任何东西。您的工作流程非常适合您所描述的场景。我将工作树看作是快速修复的文件夹,希望很快将其丢弃,或者我自己将为两个分支工作一段时间,但是共享克隆对于这两个分支都同样有效。

您的工作流程允许多个开发人员在同一台计算机上工作时共享打包的文件。一旦您使用共享存储库工作了一段时间,工作树会做得更好。新的提交可能不会被共享,而是被下载到每个单独的沙箱中。另一方面,我认为在不同的开发人员之间共享工作树不是一个好主意,但是它们可以保证链接在一起的所有工作树仅下载一个git repo副本。

我从您的设置中看到的唯一缺点是创建时间更长。但是一旦创建,这是一个很好的解决方案。

实际上,还有另外一个考虑因素,它可能不适用于您,但是值得一提:在某些情况下,git clone --shared实际上不会共享文件,例如,如果您正在穿越文件系统或安装点边界。我以前无法正确分享。但是,如果您的克隆是真正共享的,并且几乎可以肯定地以创建它们的方式获得它们,那么您就不会有这个问题。