git clone的深度是什么意思?

时间:2018-12-08 15:18:22

标签: git git-clone

我们试图加快工作中的一个软件项目的CI生成。在项目生命早期,有人提交了一些(按git的标准)巨大的二进制文件。仅仅为了摆脱git而重写git的历史似乎很麻烦,因此我们认为做一个浅表克隆可以避免那些大的早期提交就足够了。

我使用--depth参数进行了克隆实验,遇到了一些奇怪的现象。这是git clone对此的帮助:

--depth <depth>
           Create a shallow clone with a history truncated to the specified number of commits. Implies
           --single-branch unless --no-single-branch is given to fetch the histories near the tips of all
           branches. If you want to clone submodules shallowly, also pass --shallow-submodules.

这将表明<depth>将等于克隆期间将获取的提交数量,但事实并非如此。这是我尝试不同深度值时得到的:

| depth   | commit count linux repo | commit count git repo |
|---------|-------------------------|-----------------------|
| 1       | 1                       | 1                     |
| 5       | 15                      | 13                    |
| 10      | 80                      | 46                    |
| 100     | 93133                   | 39552                 |
| 1000    | 788718                  | 53880                 |

对于克隆,我使用了此命令git clone --depth 10 https://github.com/torvalds/linux.gitgit clone --depth 100 https://github.com/git/git.git,对于计数提交,我使用了此git log --oneline | wc -l。 (在工作中,我在GitLab服务器上观察到了同样的情况,因此它不能成为GitHub工作原理的产物。)

有人知道发生了什么吗?深度值如何与下载的实际数据量相对应?是我对文档的理解有误,还是存在错误?

编辑:我添加了第二次回购的结果

2 个答案:

答案 0 :(得分:4)

作为Jonathon Reinhart commented,您正在看到合并的效果。

--depth参数指的是Git从每个起点进行“行走”的深度。正如您引用的文档中提到的那样,它还暗示--single-branch,从而简化了讨论过程。这里的重点是,步行访问每个提交的所有父级,对于每个深度级别,如果提交本身是合并的,则不止一个提交。

假设我们有一个如下的提交图:

$ git log --graph --oneline master
* cf68824 profile: fix PATH with GOPATH
* 7c2376b profile: add Ruby gem support
* 95c8270 profile: set GOPATH
* 26a9cc3 vimrc: fiddle with netrw directory display
* 80b88a5 add ruby gems directory to path
[snip]

在这里,每个提交只有一个父对象。如果使用--depth 3,我们将在深度2拾取提示提交cf68824,其父7c2376b,最后在深度3拾取95c8270,然后停止,三个提交。

但是,使用Git的Git存储库:

$ git log --graph --oneline master
*   965798d1f2 Merge branch 'es/format-patch-range-diff-fix-fix'
|\  
| * ac0edf1f46 range-diff: always pass at least minimal diff options
* |   5335669531 Merge branch 'en/rebase-consistency'
|\ \  
| * | 6fcbad87d4 rebase docs: fix incorrect format of the section Behavioral Differences
* | | 7e75a63d74 RelNotes 2.20: drop spurious double quote
* | | 7a49e44465 RelNotes 2.20: clarify sentence
[snip]

--depth 3开始,我们从965798d1f2开始,然后(对于深度2)拾取父母,ac0edf1f465335669531的父母。为了添加depth-3提交,我们选择了这两个提交的所有父级。 ac0edf1f46的(唯一)父级在这里看不见,而5335669531的两个父级(即6fcbad87d47e75a63d74)。要获取ac0edf1f46的父母的哈希ID,我们可以使用:

$ git rev-parse ac0edf1f46^@
d8981c3f885ceaddfec0e545b0f995b96e5ec58f

因此,我们可以进行六次提交:master的尖端(当前为合并提交),该提交的两个父级,其中一个父级的一个父级以及该父级的另一个父级的两个父级。

>

确切地说,取决于运行Git副本的时间,最顶端的master通常不是合并,而是经常以合并作为其直接父对象,因此--depth 2常常可以帮助您3次提交,因此--depth 3至少得到 5,这取决于master尖端的两个父级本身是否合并。

(比较上面的git rev-parse输出与:

$ git rev-parse 965798d1f2^@
5335669531d83d7d6c905bcfca9b5f8e182dc4d4
ac0edf1f46fcf9b9f6f1156e555bdf740cd56c5f

例如。 ^@后缀表示提交的所有父项,但不是提交本身。)

答案 1 :(得分:-2)

--depth表示克隆时要获取的提交次数。

默认情况下git下载所有分支的所有历史记录。 这意味着您的副本将具有所有历史记录,因此您将能够“切换”(签出)任何所需的提交。

添加--depth限制克隆的大小,仅检出最后X次提交

# Cloning a  single branch with the following:
# clone specific branch and limit the history to last X commits
git clone --branch<...> --depath=<X>
  

深度值如何与实际下载的数据量相对应?   使用--depth git将下载与给定范围内的提交相对应的内容,以便在值较大时回购的大小会增加


  

这将表明它将等于

期间要提取的提交数量。

并非总是如此,如果其中任何一个提交都是合并(例如,没有快进),您将获得不止X个提交。


如何清理二进制文件:

  

重写git的历史记录以摆脱它们似乎很麻烦

此工具可以为您做到:

https://rtyley.github.io/bfg-repo-cleaner

  

BFG Repo-Cleaner

     

git-filter-branch的替代方法。

     

BFG是git-filter-branch的一种更简单,更快速的替代方法,用于从Git存储库历史记录中清除不良数据

     

*删除疯狂的大文件*
  *删除密码,凭据和其他私人数据

     

示例(来自官方网站)   在所有这些示例中,bfg是java -jar bfg.jar的别名。

# Delete all files named 'id_rsa' or 'id_dsa' :
bfg --delete-files id_{dsa,rsa}  my-repo.git