深度对于git克隆意味着什么?

gmol1639  于 2022-11-20  发布在  Git
关注(0)|答案(3)|浏览(543)

我们试图加快一个软件项目的CI构建速度。有人在项目早期提交了一些巨大的(按照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工作方式的产物)。
有人知道这是怎么回事吗?深度的值如何对应于实际下载的数据量?我对文档的理解是错误的,还是有bug?
编辑:我添加了第二个回购的结果

ni65a41a

ni65a41a1#

正如乔纳森·莱因哈特所说,你看到了合并的效果。
参数--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,我们将选择顶端提交cf68824,它的父提交7c2376b在深度2,最后95c8270在深度3-然后我们停止,有三个提交。
然而,对于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。为了添加深度3提交,我们选取这两个提交的所有父提交。ac0edf1f46(单独的)父节点在这里不可见,而5335669531的两个父代是(即6fcbad87d47e75a63d74)。要获得ac0edf1f46的父代的哈希ID,我们可以用途:

$ git rev-parse ac0edf1f46^@
d8981c3f885ceaddfec0e545b0f995b96e5ec58f

这就是我们的六个提交:主提交(当前是合并提交)的顶端、该提交的两个父提交、其中一个父提交的一个父提交以及该父提交的另一个的两个父提交。
根据你运行Git克隆的确切时间,最顶端的master通常不是merge,但通常有一个merge作为它的直接父节点,所以--depth 2通常会得到3次提交,而--depth 3会因此得到 * 至少 * 5次,这取决于master顶端的两个父节点本身是否是merge。
(将上述git rev-parse输出与以下内容进行比较:

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

后缀^@表示 * 提交的所有父提交,而不是提交本身 *。

brgchamk

brgchamk2#

--depth表示克隆时要获取的提交数。
默认情况下,git会下载所有分支的所有历史记录,这意味着你的副本将拥有所有历史记录,所以你可以“切换”( checkout )到任何你想要的提交。
添加--depth限制克隆的大小,并且只 checkout 最后X个提交

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

depth的值与实际下载的数据量如何对应?使用--depth时,git将下载与给定范围内的提交相对应的内容,因此repo的大小将在该值较大时增加
这表示将等于在

并非总是如此,如果这些提交中有任何一个是合并提交(例如,没有快进),您将获得X个以上的提交。

如何清理二进制文件:

重写git的历史只是为了摆脱他们似乎太麻烦了
此工具可为您完成以下任务:
https://rtyley.github.io/bfg-repo-cleaner

***BFG Repo-Cleaner***git-filter-分支的替代方法。

BFG是git-filter-分支的一个更简单、更快的替代方法,用于清理Git仓库历史中的坏数据

正在删除大文件

  • 删除密码、凭据和其他私人数据

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

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

pxyaymoc3#

正如其他人已经说过的,深度不是提交的次数,而是提交一个合并。这类似于find . -maxdepth 2,它不返回两个文件,而是返回这个目录及其子目录中的所有内容。
有关使用--depth的更多信息,请参见我的博客文章“Exploring Git Clone --depth“。

相关问题