我们试图加快工作中的一个软件项目的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.git
,git clone --depth 100 https://github.com/git/git.git
,对于计数提交,我使用了此git log --oneline | wc -l
。 (在工作中,我在GitLab服务器上观察到了同样的情况,因此它不能成为GitHub工作原理的产物。)
有人知道发生了什么吗?深度值如何与下载的实际数据量相对应?是我对文档的理解有误,还是存在错误?
编辑:我添加了第二次回购的结果
答案 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)拾取父母,ac0edf1f46
和5335669531
的父母。为了添加depth-3提交,我们选择了这两个提交的所有父级。 ac0edf1f46
的(唯一)父级在这里看不见,而5335669531
的两个父级(即6fcbad87d4
和7e75a63d74
)。要获取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