部分克隆

  • 随着 Git 仓库规模的增长,使用它们可能会变得很麻烦。因为:

    • 必须下载的大量历史记录。

    • 他们需要的大量磁盘空间。

部分克隆是一种性能优化,它“允许 Git 在没有完整仓库副本上工作。这项工作的目标是让 Git 更好地处理非常大的仓库”。

需要 Git 2.22.0 或更高版本。

按文件大小筛选

在 12.10 版本引入。

通常不鼓励在 Git 中存储大型二进制文件,因为之后每个克隆或获取更改的人都会下载添加的文件。如果在一个低速或者不可靠的网络环境中,这将非常慢。

部分克隆可以利用文件大小筛选器来排除麻烦的大文件,从而解决这一问题。当需要时,Git 会自行下载缺失的文件。

克隆仓库时,请使用 --filter=blob:limit=<size> 参数。例如要克隆存储库(不包括大于 1 MB的文件),请执行以下操作:

git clone --filter=blob:limit=1m git@gitlab.com:gitlab-com/www-gitlab-com.git

这将产生以下输出:

Cloning into 'www-gitlab-com'...
remote: Enumerating objects: 832467, done.
remote: Counting objects: 100% (832467/832467), done.
remote: Compressing objects: 100% (207226/207226), done.
remote: Total 832467 (delta 585563), reused 826624 (delta 580099), pack-reused 0
Receiving objects: 100% (832467/832467), 2.34 GiB | 5.05 MiB/s, done.
Resolving deltas: 100% (585563/585563), done.
remote: Enumerating objects: 146, done.
remote: Counting objects: 100% (146/146), done.
remote: Compressing objects: 100% (138/138), done.
remote: Total 146 (delta 8), reused 144 (delta 8), pack-reused 0
Receiving objects: 100% (146/146), 471.45 MiB | 4.60 MiB/s, done.
Resolving deltas: 100% (8/8), done.
Updating files: 100% (13008/13008), done.
Filtering content: 100% (3/3), 131.24 MiB | 4.65 MiB/s, done.

这个输出比较长是因为 Git 需要:

  1. 克隆仓库,但不包括大于 1 MB的文件。
  2. 下载默认分支所需的任何缺失的大文件

更改分支时,Git 可能需要下载更多丢失的文件。

按对象类型筛选

在 12.10 版本引入。

对于具有数百万个文件和较长历史的仓库,您可以使用 git sparse-checkout缩小您的工作副本。

# Clone the repo excluding all files
$ git clone --filter=blob:none --sparse git@gitlab.com:gitlab-com/www-gitlab-com.git
Cloning into 'www-gitlab-com'...
remote: Enumerating objects: 678296, done.
remote: Counting objects: 100% (678296/678296), done.
remote: Compressing objects: 100% (165915/165915), done.
remote: Total 678296 (delta 472342), reused 673292 (delta 467476), pack-reused 0
Receiving objects: 100% (678296/678296), 81.06 MiB | 5.74 MiB/s, done.
Resolving deltas: 100% (472342/472342), done.
remote: Enumerating objects: 28, done.
remote: Counting objects: 100% (28/28), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 28 (delta 0), reused 12 (delta 0), pack-reused 0
Receiving objects: 100% (28/28), 140.29 KiB | 341.00 KiB/s, done.
Updating files: 100% (28/28), done.

$ cd www-gitlab-com

$ git sparse-checkout init --cone

$ git sparse-checkout add data
remote: Enumerating objects: 301, done.
remote: Counting objects: 100% (301/301), done.
remote: Compressing objects: 100% (292/292), done.
remote: Total 301 (delta 16), reused 102 (delta 9), pack-reused 0
Receiving objects: 100% (301/301), 1.15 MiB | 608.00 KiB/s, done.
Resolving deltas: 100% (16/16), done.
Updating files: 100% (302/302), done.

有关更多详细信息,请参阅的 Git 文档sparse-checkout.

按路径筛选

可以使用 --filter=sparse:oid=<blob-ish> 过滤器规范来结合使用部分克隆和稀疏检出。此过滤模式使用类似于 .gitignore 文件指定克隆和获取时要包含的文件。

caution 使用 sparse 过滤器的部分克隆仍处于实验阶段。它可能会缓慢而显著地增加 Gitaly 克隆和获取时的资源利用率。使用过滤所有二进制文件并使用稀疏检出,因为 git sparse-checkout简化这种类型的部分克隆的使用并克服其局限性。

有关更多详细信息,请参阅的 Git 文档 rev list options

  1. 创建一个过滤器。例如,设想一个具有许多应用程序的单片存储库,每个存放在根目录的不同子目录中。创建一个文件 Shining app/.filterspec

    # Only the paths listed in the file will be downloaded when performing a
    # partial clone using `--filter=sparse:oid=shiny-app/.gitfilterspec`
    
    # Explicitly include filterspec needed to configure sparse checkout with
    # git config --local core.sparsecheckout true
    # git show master:snazzy-app/.gitfilterspec >> .git/info/sparse-checkout
    shiny-app/.gitfilterspec
    
    # Shiny App
    shiny-app/
    
    # Dependencies
    shimmery-app/
    shared-component-a/
    shared-component-b/
    
  2. 按路径克隆和筛选。使用--filter=sparse:oid 克隆命令的支持尚未与稀疏检出完全集成。

       
    # Clone the filtered set of objects using the filterspec stored on the
    # server. WARNING: this step may be very slow!
    git clone --sparse --filter=sparse:oid=master:shiny-app/.gitfilterspec <url>
       
    # Optional: observe there are missing objects that we have not fetched
    git rev-list --all --quiet --objects --missing=print | wc -l
    
    caution Git 与 ‘bash’,’zsh’ 等的集成,以及自动显示 Git 状态信息通常运行 ‘Git fetch’,它获取整个存储库。您需要禁用或重新配置这些整合。

删除部分克隆过滤

带有部分克隆过滤的 Git 仓库可以删除过滤。删除筛选:

  1. 获取过滤器排除的所有内容,以确保存储库已完成。如果使用了git sparse-checkout,请使用 git sparse-checkout disable 禁用它。请参看 disable 文档了解更多信息。

    然后定期执行fetch 以确保仓库完整。要检查是否有丢失的对象要获取,然后获取它们,尤其是在不使用 git sparse-checkout 时,可以使用以下命令:

    # Show missing objects
    git rev-list --objects --all --missing=print | grep -e '^\?'
       
    # Show missing objects without a '?' character before them (needs GNU grep)
    git rev-list --objects --all --missing=print | grep -oP '^\?\K\w+'
       
    # Fetch missing objects
    git fetch origin $(git rev-list --objects --all --missing=print | grep -oP '^\?\K\w+')
       
    # Show number of missing objects
    git rev-list --objects --all --missing=print | grep -e '^\?' | wc -l
    
  2. 重新打包所有东西。例如,可以使用 git-repack -a -d 来完成。应在 .git/objects/pack/ 中只保留三个文件:

    • 一个 pack-<SHA1>.pack 文件。

    • 它对应的 pack-<SHA1>.idx 文件。

    • 一个 pack-<SHA1>.promisor 文件。

  3. 删除 .promisor 文件。上述步骤应该只剩下一个 pack-<SHA1>.promisor 文件,该文件应为空并应删除。

  4. 删除部分克隆配置。部分克隆相关的配置变量应该从 Git 配置文件中删除。通常只需要删除以下配置:

    -remote.origin.promisor

    -remote.origin.partialclonefilter