为什么文件夹重命名、git推送到新的远程分支速度慢



我只是

  • 创建了一个新分支
  • 通过重命名顶部文件夹重命名了存储库中几乎所有的文件
  • 将分支作为新分支向上游推送

我得到

Writing objects:  26% (3337/12428), 270.49 MiB | 779.00 KiB/s 

这需要很长时间。

出于兴趣,为什么需要编写这些对象?我原以为git只是向上游发送一个"rename"命令。

它不应该(慢),至少除非你用浅存储库做棘手的事情,或者使用愚蠢的协议。但是,没有向上游发送"重命名"操作。

在内部,Git将所有内容存储为四种Git对象类型之一:提交、树、Blob(文件)和(注释)标记。

提交对象通常非常小。以下是一个真实的提交对象的示例,来自Git本身的来源:

$ git cat-file -p HEAD | sed 's/@/ /'
tree 6fe777d97b5a6fb3176d47c5ccda454deb69a8f6
parent cc00d9cfffbbeb34ee23731668656b2ebc165c85
author Junio C Hamano <gitster pobox.com> 1461960207 -0700
committer Junio C Hamano <gitster pobox.com> 1461964869 -0700
Eighth batch for 2.9
Signed-off-by: Junio C Hamano <gitster pobox.com>

当你重命名一个目录或文件时,最终得到的是一个新的"树"对象。以下是同一提交的顶级树:

$ git cat-file -p 'HEAD^{tree}'
100644 blob 5e98806c6cc246acef5f539ae191710a0c06ad3f    .gitattributes
100644 blob 05cb58a3d4ef47295fa8ef02add44a0f0dd90d1f    .gitignore
100644 blob e5b4126bec557db55924b7b60ed70349626ea2c4    .mailmap
100644 blob 78e433ba718df00d112a5f57d523afb8db189c79    .travis.yml
100644 blob 536e55524db72bd2acf175208aef4f3dfc148d42    COPYING
040000 tree 1771d89504a0003add17bffd2170f39490bad1ff    Documentation

如果我重命名COPYINGDocumentation,我会得到一个新的树对象(具有不同的ID),但.gitattributes.gitignore等的现有blob对象都将保持不变。对于Documentation/中的子树和Blob也是如此。根据您重命名的特定目录,Git可能需要一个或多个新的"树"对象来配合您的(一个)新"提交"对象。这些物体都不应该很大。

随后的git push,通过任何合理智能的协议,应该:

  • 发现它只需要发送一个新的提交对象,但需要发送许多树对象
  • 将这些对象压缩到你的Git知道(因为共享的哈希值)存在于远程Git上的对象上(在"编写对象"之前,有一个交换阶段,他们的Git告诉你他们拥有什么)
  • 编写一个"瘦包",只发送两个或五个对象,或者发送任意多的对象,这应该需要几千字节和毫秒

然后在传输阶段完成。(然后,远程设备必须"修复"瘦包,这可能需要一些时间,并验证推送是否允许,如果允许,则在发送确认或故障响应之前更新远程存储库。)

最新更新