4

相关问题:为什么 Git 每次 push origin master 时都会发送整个存储库

简短版本:当使用两个 Git 存储库时,即使 99% 的提交对象是相同的,当设置为指向存储库Agit push时,使用将提交发送到存储库B会导致所有对象 (200MB +) 被传输。origin

更长的版本:我们在持续集成服务器上设置了第二个 Git 存储库。在我们在本地准备好我们的提交对象之后,而不是origin/master像通常那样直接推送到,而是将我们的更改推送到第二个存储库上的一个分支。CI 服务器选择新的分支,将其自动变基到master,运行我们的集成测试,如果一切顺利,将分支推送到origin/master主存储库。

CI 服务器还定期调用git fetch以从主存储库中检索最新副本origin/master,以防有人绕过 CI 流程并直接推送。

这非常有效,特别是如果git fetch; git rebase origin/master在推送到 CI 回购之前做了一个;Git 只发送尚未在origin/master. 如果在推送之前跳过 fetch/rebase 步骤,该过程仍然有效,但 Git 似乎将大部分提交对象(如果不是全部)发送到 CI 存储库 - 目前价值超过 200MB。(我们的 repo 的新克隆为 225MB。)

我们做错了什么吗?有没有办法纠正这种行为,使 Git 只发送它需要在 CI 存储库上形成分支的提交对象?我们显然可以通过 pre-push 来解决这个问题git fetch; git rebase origin/master,但感觉我们应该能够跳过这一步,特别是因为直接推送到主仓库不会出现同样的问题。

我们的存储库由 Gitosis 0.2 提供服务,我们的客户绝大多数都在运行 msysgit 1.7.3.1-preview。

4

3 回答 3

2

...自动将其重新定位到master...

我认为这就是问题的根源。每次您的 CI 服务器执行此自动变基步骤时,它都会创建一组全新的提交,这些提交相对于当前分支和主分支最近的共同祖先。

下次您将代码推送到 CI 服务器时,它实际上不再拥有所有这些对象(它们无法从任何活动头访问),因此它要求您的客户端再次发送它们。

您应该能够通过查看您所做的提交的 SHA1 提交 ID 来看到这种情况。您可能会发现本地提交的提交 ID 不再与 CI 服务器上的 rebased 分支中的相应提交 ID 匹配。

于 2010-11-05T00:23:34.027 回答
2

事实证明,这个问题最简单的解决方案在推送之前获取:

$ git fetch origin master
$ git push user@host:repo.git HEAD:refs/heads/commit128952690069

在我们的例子中,获取一个特定的分支到FETCH_HEAD;是很重要的。这样,用户的本地分支状态将不受影响,但我们仍会从主存储库中收到最新的一组对象;当 Git 开始打包对象时,以下内容git push将始终存在祖先提交。

我做了一些工具git pack-objects:如果构建一个包含提交的包文件<common_ancestor>..HEAD,它只打包所需的数据:

$ echo $(git merge-base master origin/master)..HEAD | git pack-objects --revs --thin --stdout --all-progress-implied > packfile

但是,git push以相同状态发布存储库会导致所有对象都被打包和发送。

我怀疑发生的情况是,在连接到 Git 存储库时,会收到存储库中最新修订版的 SHA——如果 Git 在本地没有该 SHA 表示的提交对象,它就无法运行git merge-base以确定共同祖先;因此,它必须将所有对象发送到远程仓库。如果该提交对象确实存在,则git merge-base成功,并且可以参考共同祖先来构建包文件。

于 2010-11-12T02:37:07.223 回答
0

听起来您的本地存储库与 CI 服务器存储库不同步,从您推送到 CI 服务器的事实意味着您的本地存储库具有一组不同的提交哈希。它可能是这样的:

git克隆大师
(... 做工作 ...)
git push ci 分支
(...... CI 做了一个 rebase,改变了你推送的所有提交哈希..)
(...... CI 进行测试并推动掌握......)
(... 现在 master 和 CI 匹配但是你刚刚推送的所有提交的哈希值
     除了您的本地机器外不存在任何地方...)
(... 做工作 ...)
git push ci 分支

最后一次推送将包含您第一次推送的整个提交集,因为 CI 的变基更改了它们的所有哈希值,而您仍在处理您创建的原始提交。

于 2010-11-05T16:51:23.127 回答