是否有支持部分结账/克隆的分布式版本控制系统?

Jak*_*kob 15 git version-control mercurial dvcs bazaar

据我所知,所有分布式版本控制系统都要求您克隆整个存储库.因此,将大量内容放入一个存储库并不明智(感谢您的回答).我知道这不是一个bug而是一个功能,但我想知道这是否是所有分布式版本控制系统的要求.

在分布式rcs中,文件(或一大块内容)的历史记录是有向无环图,那么为什么不能克隆这个单个DAG而不是存储库中所有图形的集合?也许我想念一些东西,但以下用例很难做到:

  • 克隆只是存储库的一部分
  • 合并两个存储库(保留它们的历史!)
  • 将一些文件从一个存储库复制到另一个存储库

如果我从多个项目中重用其他人的代码部分,我无法保留其完整的历史记录.至少在git中我可以想到一个(相当复杂的)解决方法:

  1. 克隆完整的存储库
  2. 删除我不感兴趣的所有内容
  3. 重写历史记录以删除主文件中没有的所有内容
  4. 将剩余的存储库合并到现有存储库中

我不知道Mercurial或Bazaar是否也可以这样做,但至少它根本不容易.那么是否有任何支持部分检出/克隆的分布式rcs?它应该支持一个简单的命令,从一个存储库获取包含其历史记录的单个文件,并将其合并到另一个存储库 这样您就不需要考虑如何将内容构建到存储库和子模块中,但您可以根据需要快乐地拆分和合并存储库(极端情况是每个文件的一个存储库).

Mar*_*ler 7

从版本2.0开始,不可能使用Mercurial 制作所谓的"窄克隆",也就是说,只能检索特定子目录的数据的克隆.当你只检索部分历史记录时,我们称之为"浅层克隆",例如,最后100次修订.

正如您所说,基于DAG的常见历史模型中没有任何内容排除此功能,我们一直在努力.Mercurial撰稿人Peter Arrenbrecht对窄克隆实施了两种不同的方法,但这两种方法尚未合并.

顺便说一下,您当然可以将现有的Mercurial存储库拆分成多个部分,其中每个较小的存储库只包含原始存储库的特定子目录的历史记录.该转换的扩展是这个工具.尽管如此,每个较小的存储库都与较大的存储库无关 - 棘手的部分是使拆分无缝,以便更改集保持其身份.


kwa*_*ord 5

git有一个子树模块,允许您将存储库的一部分拆分为新的存储库,然后将更改合并到原始子树和子树.这是关于github的自述文件:http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt


Gre*_*ill 5

在分布式rcs中,文件(或一大块内容)的历史记录是有向非循环图,那么为什么不能克隆这个单个DAG而不是存储库中所有图形的集合?

至少在Git中,表示存储库历史的DAG适用于整个存储库,而不仅仅是单个文件.每个提交对象都指向一个"树"对象,该对象表示当时存储库的整个状态.

Git 1.7支持"稀疏检出",允许您限制工作副本的大小.但是,仍然克隆了整个存储库数据.


Von*_*onC 5

正如吉特2.17(Q2 2018年,10年后),那有可能做什么水银计划实施:一个“ 窄克隆 ”,即克隆,你只对一个特定的子目录中检索数据。
这也称为“部分克隆”。

与目前不同

  • 浅克隆
  • 在另一个工作文件夹中的克隆存储库中所需信息的副本。

请参阅Jeff Hostetler(提交的commit 3aa6694commit aa57b87commit 35a7ae9commit 1e1e39bcommit acb0c57commit bc2d0c3commit 640d8b7commit 10ac85c(2017年12月8日。 请参阅Jonathan Tan(提交的commit a1c6d7ccommit c0c578bcommit 548719fcommit a174334commit 0b6069f(2017年12月8日(通过合并JUNIOÇ滨野- -提交6bed209jeffhostetler
jhowtan
gitster,2018年2月13日)

以下是部分克隆测试

git clone --no-checkout --filter=blob:none "file://$(pwd)/srv.bare" pc1 
Run Code Online (Sandbox Code Playgroud)

还有其他参与窄/部分克隆的是实现其他的提交

特别是commit 8b4c010

sha1_file:支持延迟获取丢失的对象

教每当请求但丢失sha1_file对象时,从配置的远程中获取对象 extensions.partialclone


关于Git 2.17 / 2.18的警告:最近添加了“部分克隆”实验功能,该功能在不应该extensions.partialclone启用的情况下开始使用,即,即使设置了也没有定义部分克隆过滤器。

参见Jonathan Tan()的commit cac1137(2018年6月11日(由Junio C Hamano合并--commit 92e1bbc中,2018年6月28日)jhowtan
gitster

upload-pack:在配置禁用时禁用对象过滤

upload-pack获得部分克隆支持(v2.17.0-rc0〜132 ^ 2〜12,2017-12-08)时,它受到uploadpack.allowFilterconfig项的保护,以允许服务器操作员控制何时开始支持克隆。

但是,该配置项还远远不够:它控制是否发布' filter'功能,但是如果(自定义)客户端忽略功能发布并通过过滤器规范,则尽管allowFilter为false,服务器仍将处理该配置项。

如果在此新的实验性部分克隆代码中发现了安全漏洞,则这尤其重要。
没有安装的设备不uploadpack.allowFilter应该受到影响,因为它们不打算支持部分克隆,但是它们会变得脆弱。


Git 2.20(Q2 2018)增强了此功能,因为git fetch $repo $object部分克隆中的“ ”未正确获取由Promisor Packfile中的对象引用的所需对象。

参见Jonathan Tan()的commit 35f9e3ecommit 4937291(2018年9月21日(由Junio C Hamano合并--commit a1e9dff中,2018年10月19日)jhowtan
gitster

fetch:在部分克隆中,检查目标的存在

时,取该被称为一个允诺目的是本地资源库的对象,在连通性检查quickfetch()builtin/fetch.c 成功时,使对象传送到被旁路。
但是,如果仅承诺该对象而不实际提供该对象,则不应发生这种情况。

因为发生这种情况,所以当用户git fetch origin <sha-1>在命令行上调用“ ”时,<sha-1>即使命令返回的退出代码为0 ,也可能实际上并未提取该对象。这与已修复的问题类似(但原因不同)通过a0c9016 (“上传包:尽管存在“过滤器”,但仍发送裁判的对象”,2018-07-09,Git v2.19.0-rc0)。

因此,进行更新quickfetch()以也直接检查是否存在要提取的所有对象。


您可以使用以下命令列出部分克隆的对象(“承诺”对象除外): git rev-list --exclude-promisor-objects

(仅供内部使用。)在允诺者边界处预过滤对象遍历。
与部分克隆一起使用
这比--missing=allow-promisor因为它限制遍历而不是仅仅消除有关丢失对象的错误而更强大。

但是请确保使用Git 2.21(2019年第一季度)来避免出现段错误。

参见Matthew DeVore()的commit 4cf6786(05 Dec 2018 (由Junio C Hamano合并--commit c333fe7中,2019年1月14日)matvore
gitster

git rev-list --exclude-promisor-objects”必须从命令行中获取本地不存在的对象(并且可以懒惰地使用),而无需使用barfing,但是代码取消了对NULL的引用。

list-objects.c:不要对缺少的cmdline对象进行分段处理

当同时使用--exclude-promisor-objects--objects-edge-aggressive和命令行中缺少的对象来调用命令时,该rev_info.cmdline数组可以获得一个' item'字段值的NULL指针。在这种情况下,请
避免取消对NULL指针的引用。


请注意,Git 2.21(2019年第一季度)修复了一个错误:

参见Matthew DeVore()的commit bbcde41(2018年12月3日(由Junio C Hamano合并--commit 6e5be1f中,2019年1月14日)matvore
gitster

exclude-promisor-objects:声明何时允许选项

--exclude-promisor-objects选项在至少两个命令中引起一些有趣的行为:logblame
它会导致BUG崩溃:

$ git log --exclude-promisor-objects
BUG: revision.c:2143: exclude_promisor_objects can only be used
when fetch_if_missing is 0
Aborted
[134]
Run Code Online (Sandbox Code Playgroud)

修复此问题,使该选项与其他任何未知选项一样被对待。
必须支持它的命令是有限的,因此请在那些命令中声明支持该标志。
特别是:

pack-objects
prune
rev-list
Run Code Online (Sandbox Code Playgroud)

通过搜索在--exclude-promisor-objects之外解析的逻辑来找到命令revision.c
需要额外的逻辑,revision.c因为fetch_if_missing必须先打开revision.c该逻辑才能看到该选项,否则它将导致BUG崩溃。上面的列表由以下事实支持:另一个传递的命令不会内省地调用其他命令--exclude-promisor-object


Git 2.22(2019年第二季度)优化了狭窄的克隆:
git diff惰性克隆中运行“ ”时,我们可以预先知道我们需要哪些丢失的Blob,而不必等待按需的机制一个个地发现它们。
旨在通过批量处理这些承诺的Blob的请求来获得更好的性能。

提交7fbbcb2(2019年4月5日),并提交0f4a4fb(2019年3月29日)由乔纳森·谭(jhowtan
(通过合并JUNIOÇ滨野- gitster-提交32dc15d,2019年4月25日)

diff:批量获取丢失的斑点

在部分克隆中运行“ git show”或“ git diff”之类的命令时,请批量处理所有丢失的blob以作为一个请求来获取。

这类似于c0c578b(“ unpack-trees:批量提取丢失的斑点”,2017-12-08,Git v2.17.0-rc0),但是用于另一个命令。


Git 2.23(2019年第三季度)将对批量丢失的blob部分进行未来验证。

参见Derrick Stolee(提交31f5256(2019年5月28日(由Junio C Hamano合并--commit 5d5c46b中,2019年6月17日)derrickstolee
gitster

sha1-file: 分裂 OBJECT_INFO_FOR_PREFETCH

OBJECT_INFO_FOR_PREFETCH位标志加入到sha1-file.c0f4a4fbsha1-file:支持OBJECT_INFO_FOR_PREFETCH,2019年3月29日,GIT中v2.22.0-RC0),并用于防止fetch_objects()方法启用时。

但是,目前的使用存在问题。
的定义OBJECT_INFO_FOR_PREFETCH是将加上32 OBJECT_INFO_QUICK
如此OBJECT_INFO_FOR_PREFETCH暗示的定义(在注释中)清楚地指出了这一点 OBJECT_INFO_QUICK
问题是,使用“ flag & OBJECT_INFO_FOR_PREFETCHOBJECT_INFO_QUICK也意味着隐含OBJECT_INFO_FOR_PREFETCH

将一个位从OBJECT_INFO_FOR_PREFETCH一个新位拆分为一个新 OBJECT_INFO_SKIP_FETCH_OBJECT位,并保持 OBJECT_INFO_FOR_PREFETCH两个标志的并集。

而将“ git fetch”放入一个懒惰的克隆中却忘记了获取已完成的瘦包文件中完成增量所必需的基础对象。

提交810e193提交5718c53(2019年6月11日),并提交8a30a1e提交385d1bf(2019月14日)由乔纳森·谭(jhowtan
(由Junio C gitsterHamano合并--8867aa8号提交中,2019年6月21日)

index-pack:预取缺少的REF_DELTA碱基

提取时,客户端会发送have提交ID,以指示服务器不需要发送这些提交所引用的任何对象,从而减少了网络I / O。
当客户端是部分克隆时,即使客户端have没有提交所引用的每个对象,客户端仍然会以这种方式发送消息have

如果服务器省略了这样的对象,那就很好了:客户端可以在获取之前懒惰地获取该对象,而在获取之后仍然可以这样做。

问题是服务器发送包含对象的瘦包时,该瘦包REF_DELTA针对此类丢失的对象:index-pack无法修复瘦包。
当在8b4c010中添加了sha1_file对延迟获取丢失的对象的支持(“ :支持延迟获取丢失的对象”,2017-12-08,Git v2.17.0-rc0)时,index-pack由于认为它仅访问存储库,因此关闭支持进行哈希冲突检查。
但是,事实并非如此:它还需要访问存储库来解析 REF_DELTA库。

通常,应该在索引包中关闭对延迟获取的支持,因为它被用作延迟获取过程本身的一部分(如果没有,则可能会发生无限循环),但是我们确实需要获取REF_DELTA基数。
(在获取REF_DELTA基数时,它们本身不太可能REF_DELTA,因为have在进行此类获取时我们不会发送“ ”。)

要解决此问题,请REF_DELTA在尝试解决所有缺失的碱基之前先进行预取。
这既确保了尝试获取所有基础,又确保了每次索引包调用仅发出一个请求,而不为每个丢失的对象发出一个请求。


Git 2.24(Q4 2019)修复了延迟克隆中的按需对象获取,该克隆错误地尝试从子模块项目中获取提交,同时仍在超级项目中工作。

参见Jonathan Tan(提交的commit a63694f(2019年8月20日(通过合并JUNIOÇ滨野- -提交d8b1ce7,2019年9月9日)jhowtan
gitster

diffGITLINK懒惰获取缺少的obj时跳过

7fbbcb2(“ diff:批量获取丢失的对象”中,2019-04-08,Git v2.22.0-rc0)中,我们diff教给在部分克隆上进行操作时批量获取丢失的对象,但并未被教导不要获取GITLINK。
教diff在将对象GITLINK