我想知道git在推动变化时做了什么,以及为什么它似乎偶尔会推动更多的数据而不是我所做的改变。我对两个增加了大约100行代码的文件进行了一些更改 - 不到2k的文本,我想象。
当我将数据推送到原点时,git将其转换为超过47mb的数据:
git push -u origin foo
Counting objects: 9195, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6624/6624), done.
Writing objects: 100% (9195/9195), 47.08 MiB | 1.15 MiB/s, done.
Total 9195 (delta 5411), reused 6059 (delta 2357)
remote: Analyzing objects... (9195/9195) (50599 ms)
remote: Storing packfile... done (5560 ms)
remote: Storing index... done (15597 ms)
To <<redacted>>
* [new branch] foo -> foo
Branch foo set up to track remote branch foo from origin.
当我区分我的更改时,(origin / master..HEAD)只显示了两个文件和一个提交。 47mb的数据来自哪里?
我看到了这个:When I do "git push", what do the statistics mean? (Total, delta, etc.) 而这:Predict how much data will be pushed in a git push 但那并没有真正告诉我发生了什么......为什么包/捆绑会很大?
答案 0 :(得分:5)
我刚刚意识到非常现实的情况会导致非常大的推动。
推送什么对象发送?服务器上尚不存在。或者,而不是它现有的检测。它如何检查对象的存在?在推送开始时,服务器发送有的引用(分支和标签)。因此,例如,如果他们有以下提交:
QTcpSocket* socket = new QTcpSocket();
socket->setSocketDescriptor(socketDesc); // socketDesc is a point of type qintptr
然后客户端将获得类似 CLIENT SERVER
(foo) -----------> aaaaa1
|
(origin/master) -> aaaaa0 (master) -> aaaaa0
| |
... ...
的内容,并发现它必须仅发送提交/refs/heads/master aaaaa0
中的新内容。
但是,如果有人将任何东西推到了远程掌握,那就不同了:
aaaaa1
此处,客户端获取 CLIENT SERVER
(foo) -----------> aaaaa1 (master) --> aaaaa2
| /
(origin/master) -> aaaaa0 aaaaa0
| |
... ...
,但它对aaaaa2 一无所知,因此无法推断服务器上存在refs/heads/master aaaaa2
。因此,在这个只有2个分支的简单情况下,将发送整个历史记录,而不是仅增加历史记录。
这不太可能发生在成长,积极开发,项目,其中有标签和许多分支,其中一些变得陈旧,不会更新。因此,用户可能会发送更多信息,但它并没有像您的情况那样变得那么大,并且没有任何损失。但是在非常小的团队中,它可以更频繁地发生,而差异将是巨大的。
为避免这种情况,您可以在推送之前运行aaaaa0
。然后,在我的示例中,git fetch
提交已存在于客户端,而aaaaa2
会知道它不应发送git push foo
及更早的历史记录。
阅读here以了解协议中的推送实现。
PS:最近的git commit graph功能might help with it,但我没有尝试过。
答案 1 :(得分:3)
当我将数据推送到原点时,git将其转换为超过47mb的数据..
看起来您的存储库包含大量二进制数据。
git-push
- 更新远程引用以及关联对象
associated objects
是什么?每次提交后,你都会把git执行pack
个数据到名为的文件中
XX.pack
&amp;&amp; `XX.idx'
有关包装的好读物是here
打包存档格式
.pack
旨在自包含,以便在没有任何进一步信息的情况下解压缩。
因此,delta所依赖的每个对象必须存在于包中。生成包索引文件
.idx
,以便快速随机访问包中的对象。将索引文件
.idx
和压缩存档.pack
放在pack
的{{1}}子目录(或$GIT_OBJECT_DIRECTORY
上的任何目录)中Git从包存档中读取。
当git打包你的文件时,它会以智能的方式完成它,因此它将非常快速来提取数据。
为了实现这个git,使用pack-heuristics基本上在你的包中寻找类似的内容部分并将它们存储为单个内容,这意味着 - 如果你有许多相同的标题(例如许可协议)文件,git将“找到”它并将存储一次。
现在,包含此许可证的所有文件都将包含指针到标头代码。在这种情况下,git不必反复存储相同的代码,因此包大小很小。
这是为什么它不是一个好主意并且不建议在git中存储二进制文件的原因之一,因为具有相似性的可能性非常低,因此包大小将不是最佳的。
Git以压缩格式存储您的数据以减少空间,因此再次二进制文件也不是最佳的,因为压缩(大小为wize)。
以下是使用压缩压缩的git blob示例: