git push 对于一个分支来说非常慢

标签 git

我们有一个非常大的 git 存储库(ios 应用程序资源)。我明白 git 在使用它时会变慢,但如果我创建一个新分支并编辑几个文件(不是二进制文件)并推送,它会花费很长时间。

感觉整个repo都在push了。我的印象是 git 只会发送差异,这是错误的吗? (我知道 git 存储整个文件的压缩版本,我的意思是我的分支和我分支的地方之间的差异)。

如果我运行 git diff --stat --cached origin/foo 然后我会看到一个简短的文件列表,看起来像我所期望的,例如34 ​​个文件已更改,1117 个插入 (+),72 个删除 (-)。但是当我 push 它到达 Writing objects: 21% (2317/10804) 并逐渐停止时,就好像它正在 push 所有 2.4GB 的二进制数据。

我是不是遗漏了什么(我用谷歌搜索得很辛苦)?这是预期的行为吗?我在 OS X (Mavericks) 和 ssh (git@github.com) 上使用 git 2.2.2。

我在这里发现了一个类似的问题:Git - pushing a remote branch for a large project is really slow但没有真正的答案。

最佳答案

您正在使用“智能”传输(这是一件好事),因此您确实获得了增量,或者更具体地说,是“增量压缩”。但这并不是说 git push 了差异。

推送和获取在这里的工作方式相同:在智能传输上,您的 git 调用远程并且两端进行小型对话以确定谁拥有哪些存储库对象,由 SHA-1 识别并附加到特定标签(通常是分支和标签名称,但也允许使用其他标签)。

例如,在这种情况下,您的 git 调用他们的并说:“我建议您将分支 master 设置为 SHA-1 1234567... . 我看到你的 master 当前是 333333...,我认为你需要从那里到 7777777...。 “他们应该回复“好的,我需要其中一些,但我已经有了……”。一旦您的 git 确定了需要发送的内容以及已经存在的内容,您的 git 就会构建一个“瘦包”1,其中包含所有要发送的对象。 (这是“最多使用 %d 个线程进行增量压缩”阶段。)

然后通过智能传输发送生成的薄包;这是您看到“写入对象”消息的地方。 (必须成功发送整个精简包,之后接收方使用 git index-pack --fix-thin 再次“加肥”并将其放入存储库。)

具体发送什么数据,取决于薄包中的对象。 应该只是“他们拥有的”和“您正在发送的”之间的一组提交,加上这些提交所需的任何对象(树和 blob),以及您要添加的任何带注释的标签发送和那些需要的任何对象,他们还没有。

您可以通过使用 git fetch 获取他们的最新信息,然后使用 git rev-list 查看您要发送给他们的提交来找到有问题的提交.例如,如果你只是想在 master 上推送东西:

$ git fetch origin   # assuming the remote name is origin
[wait for it to finish]
$ git rev-list origin/master..master

检查这些提交可能会显示一个非常大的二进制文件,它包含在中间的一个文件中,然后在以后的提交中再次删除:

$ git log --name-status origin/master..master

如果一个提交有 A giantfile.bin,然后后续(可能在 git log 输出中首先列出)提交有 D giantfile.bin,您可能在发送 giantfile.bin 的 blob 时挂断了。

如果是这样,你可以使用 git rebase -i 来消除添加巨型二进制文件的提交,这样 git push 就不必发送了那个提交。

(如果您的历史是线性的——没有要推送的 merge ——那么您也可以使用 git format-patch 创建一系列包含补丁的电子邮件消息。这些是合适的用于向其他站点的某人发送电子邮件——并不是说 github 上有人在等待接收它们,但您可以轻松地检查补丁文件以查看它们是否庞大。)


1这个包是“瘦”的,因为它违反了一个正常的包文件规则,该规则要求任何增量压缩“下游”对象都在包本身中。相反,“下游”对象可以(事实上,必须)位于接收精简包的存储库中。

关于git push 对于一个分支来说非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29118876/

相关文章:

git - 如何一次 rebase 多个分支?

django - Git - 如何将代码从我的中央 Git 存储库部署到我的生产服务器?

git:如何同步到最新版本

git - 将 master 重置为之前的提交 - 如何推送

git - Git 分支级别的用户权限?

git - 跨平台 git 配置的最佳实践?

git 预提交 + mysqldump : cannot find path, 不存在命令

git - 在 CentO 上安装 Git

git - 如何从另一个分支中获取一个文件,但当前分支中不存在该文件?

git - 如何接受差异文件的修订?