将git存储库一直克隆到特定提交,但不是全部

将git存储库一直克隆到特定提交,但不是全部,git,Git,让我们举一个例子。 假设我们想要一个本地副本,但只对它最近的历史感兴趣,而且由于这个repo有着巨大的历史,我们想要做一个浅层克隆,以便git操作更快地工作(它不必每次都解析整个历史,只解析我们本地拥有的) 好吧,让我们想想我们需要回去多远。假设v4.0是我们想要的最早版本,我们如何将其转换为--深度 $ git rev-list --count v4.0..torvalds/master 95302 所以从v4.0开始,master上已经有95302次提交,听起来应该是正确的深度,对吧?让我

让我们举一个例子。
假设我们想要一个本地副本,但只对它最近的历史感兴趣,而且由于这个repo有着巨大的历史,我们想要做一个浅层克隆,以便git操作更快地工作(它不必每次都解析整个历史,只解析我们本地拥有的)

好吧,让我们想想我们需要回去多远。假设
v4.0
是我们想要的最早版本,我们如何将其转换为
--深度

$ git rev-list --count v4.0..torvalds/master
95302
所以从
v4.0
开始,master上已经有95302次提交,听起来应该是正确的深度,对吧?让我们试试:

$ git clone --depth=95302 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Cloning into 'linux'...
remote: Counting objects: 4791958, done.
remote: Compressing objects: 100% (3558/3558), done.
remote: Total 4791958 (delta 2188), reused 640 (delta 174), pack-reused 4788216
Receiving objects: 100% (4791958/4791958), 1.49 GiB | 12.93 MiB/s, done.
看起来已经有很多了。让我们看看它有多远:

$ git -C linux tag | head
v2.6.12
v2.6.12-rc2
v2.6.12-rc3
v2.6.12-rc4
v2.6.12-rc5
v2.6.12-rc6
v2.6.13
v2.6.13-rc1
v2.6.13-rc2
v2.6.13-rc3
好吧,很明显我们在这里赚的太多了

我如何计算要取多少,即要请求什么
--深度?

编辑:明确地说,目标是拥有一些旧提交和现在提交之间的历史记录(如果它允许在这之后获取新提交,就像浅层克隆一样,这是一个额外的点)。 破坏历史的答案(如目前给出的答案)显然不能满足这一点

我刚刚发现了关于git replace的
git replace
,它可能能够在提交之前移植一个压缩版本的历史记录。我将试一试,并根据结果更新此问题/回答

我们只对它最近的历史感兴趣。。。我们如何把它转换成深度

除非有一个完整的克隆,然后断开不需要的数据,否则无法执行此操作

要做到这一点,您有几种方法:

  • 克隆整个repo,然后创建一个孤立分支,并从所需的点到末尾挑选所有提交

  • 与上述类似:

    git clone --branch <tag_name> <repo_url>
    # or 
    git checkout tags/<tag_name>
    
    git克隆——分支
    #或
    git签出标记/
    
  • 克隆
    ,然后执行
    重置--hard
    到所需的点+
    挤压
    以将所有提交合并到单个提交


  • 我相信git并没有提供一种方法来克隆回一个给定的提交。至少
    rev list
    似乎没有足够的选项来输出与
    --depth
    兼容的计数

    不过,您可以用git clone--depth以某种方式实现它(关于评论,请注意:我假设整个练习旨在避免最终存储库中的积垢,并且您在初次完全下载时没有遇到问题,即网络使用对您来说没有问题,并且您有足够的硬盘空间暂时容纳较大的存储库):


    也就是说,使用一些人类启发法进行二进制搜索……它不应该花费太多的尝试,并且可以编写脚本


    编辑:更改了答案,使其只在网络上下载一次。

    一般来说,如果没有克隆,就无法下载,因此这有点傻,但是:你需要计算深度,而不是提交(后者包括宽度:简单的例子,假设分支X的尖端是一个合并,您需要在X^到X^^或X^2到X^^之后进行2次提交才能达到目标;
    rev list--count
    将计数3,但由于缺少
    --boundary
    而导致的围栏错误除外).
    --第一个父级
    也不总是有效的,但这只是一个开始,就像
    --祖先路径
    一样。你可能还想在克隆步骤上使用
    --单分支
    。@torek,
    --单分支
    --深度
    中暗示了这一点。@AnoE:哦,我明白了,确实如此!谢谢。“我们想做一个浅层克隆,这样[…]它不必每次都解析整个历史,“……具体来说,你在说什么操作?@jthill:据我所知,所有的git操作都使用浅层克隆(只要你在第一次提交之前不尝试访问内容)。这至少包括我每天使用的操作(在我脑海中):日志、差异、提交、推送、获取、拉取、重新基址、格式化补丁、am、rev parse/-list、分支、签出和重置。所以你的答案是“我没有答案,但你可以做这些其他事情”?回答你的建议:(1)和(3)将丢失历史,使试图首先说出历史的观点无效,(2)无法满足问题的任何要求。我将编辑问题,以明确丢失历史会适得其反。“不应该尝试太多(大约10-15次)。”→ 我不知道你是不是在玩游戏,但以防万一,你不是:Linux内核有2个多一点⁰–2¹⁵ (1k–32k)提交。目前在
    主机上有602598个提交,进行这样的克隆平均下载大约1GB(0–1.6GB)每一次,您的解决方案不仅是我所能想到的最低效的,而且浪费了大量带宽,而且还需要几天才能运行。我不是在闲逛。我们不是在谈论602598次提交,海报已经找到了95000次提交的上限。
    log2(95000)=17
    ,这将是二进制搜索的上限。他可以通过克隆本地克隆来避免重复下载。而且,恕我直言,与Youtube&Co每天传输的大量数据相比,即使是120MB的
    --depth=1
    linux内核克隆也只是一个很小的数据量!我想他不会这么做(寻找正确深度的)操作当然不止一次是从零开始的。好吧,我很抱歉,我不应该这样回答。是的,本地克隆会比从网络上获取它们更快,更少浪费,但这种暴力技术看起来并不太好。而
    v4.0
    示例就是,一个示例,实际值会有所不同(在较大的方面).我不确定我是否理解你关于其他事情更大的观点。无论如何,我对你的答案投了更高的票,因为它确实回答了这个问题,尽管这不是最好的方式(这是主观的)。当我
    git clone --depth=95302 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux-95k
    
    git clone --depth=10000 file://`pwd`/linux-95k linux
    
    # oops, too little!
    
    rm -rf linux
    git clone --depth=50000 file://`pwd`/linux-95k linux
    
    # oops, still too much!
    
    ...