拆分 git bundle文件



有没有办法拆分 git 捆绑文件?比如说,repo.bundle1 和 repo.bundle2,每个都包含一半的存储库。便携式捆绑包的尺寸太大,无法传输。

假设允许传输的最大大小无法更改,我还能如何处理这个问题。

捆绑包可以是增量的。

它们不能有悬而未决的提交,所以如果你想增量捆绑一个现有的分支,你必须玩一些游戏。

它们必须"按顺序"应用,以便在应用捆绑包时,其根提交的父级可以锁定。 (可能有一种方法可以通过浅存储库解决此问题,但是如果您尝试最终重建整个存储库,那么您将不必担心这一点。

当然,如果任何单个提交太大(例如,由于提交非常大的文件),那将是一个问题。

假设你有

x -- x -- x <--(branch1)
/
A -- B -- C -- D -- E -- F -- G -- H -- I -- J <--(master)
      /
o -- o <--(branch2)

并假设您想将其分解为不超过 3 次提交的捆绑包。 因此,让我们从根源开始。 我们将逐步移动master分支,因此让我们跟踪其当前位置。

git checkout master
git tag real_master

现在我们查找C的 SHA ID(或找到一些其他引用C的名称,例如在本例中为master~7),然后

git reset --hard master~7

请注意,我使用的是硬重置;这可能不是必需的,但我假设您可以从具有干净工作树的存储库中执行此操作,在这种情况下,进行硬重置会使所有内容保持良好,简单的状态(无论如何,正如我所看到的)。

我们已准备好创建我们的第一个捆绑包

git bundle create 0.bundle master

这个捆绑包包括B,它是branch1的根,所以我们现在可以捆绑branch1

git bundle create 1.bundle master..branch1

这相当于

git bundle create 1.bundle ^master branch1

无论哪种方式,我们都是假设接收存储库已经具有可从master访问的ocmmit,因此只有x提交将放置在此捆绑包中。

看起来DEF是下一个合乎逻辑的步骤;但F取决于brnach2中提交o。 因此,下一个合乎逻辑的事情实际上是将branch2D捆绑在一起。 既然我们还有masterC我们可以说

git bundle create 2.bundle master..branch2

现在我们需要将master移动到G,以便我们可以捆绑EFG。 确保我们在master

git reset --hard real_master~3
git bundle create 3.bundle ^branch2 ^master~3 master

在这里,我注意到较旧的主线历史记录和branch2历史记录都可以从master访问(通过F处的合并),但由于它们都已经捆绑在一起,因此我都排除了它们。

最后

git reset --hard real_master
git tag -d real_master
git bundle create 4.bundle master~3..master

实际上,您可能会在每个捆绑包中使用 3 个以上的提交。 如果你有一个本身太大的侧分支,你可以使用我们在这个例子中用于分割master的相同技术来分解它。

现在,您可以独立传输它们,并从中获取(或拉取)它们,以便在另一端重建存储库。

更新

另外两个注意事项:


首先,与ElpieKay建议使用ddcat相比,上述方法有利有弊。

它只依赖于 git 本身(尽管dd/cat方法所需的实用程序通常随 git 一起提供)。

各个捆绑包文件本身都很有用,而如果您使用dd对文件进行分段,则必须重建所有部件以确保您有一个可用的捆绑包。 这也意味着您可以保存捆绑包并将它们与您以后创建的其他捆绑包组合(随着更多更改的发生);但是,仅当您需要从头开始创建另一个新的远程存储库时,这才有意义。

实际上,只是来回发布增量更改,其中双方已经有一个共同的提交基线,是捆绑包的基本用例。 因此,您可能决定使用dd/cat方法最初创建远程存储库,然后使用增量捆绑包进行后续更新共享。

dd/cat方法的最大优点是它非常死记硬背/可编写脚本(即假设工具在手边很简单),而你必须考虑如何为上述方法划分提交;而且dd方法可以拆分单个令人讨厌的大提交,如果结果是一个。


我最初也忘了提到,您可以列出要包含在捆绑包中的多个分支。 因此,例如,如果您的阈值更像是每个捆绑包 8 次提交,您可以

1) 将master移至E

2) 捆绑masterbranch1为 0.捆绑

3) 将master移回J

4) 捆绑master不包括master~5作为 1.捆绑

并完成。

命令dd可以将文件拆分为多个部分。cat可以将各个部分组合成一个整体。

假设我们发现repo.bundle是 1466712k,大约 1.4g,通过du repo.bundle。假设限制为 1g。我们可以repo.bundle分成 2 个文件,一个是 700m,另一个是 700m 多一点,以便可以传输它们。

dd if=repo.bundle bs=1048576 count=700 skip=0 of=repo.bundle1
dd if=repo.bundle bs=1048576 skip=700 of=repo.bundle2

bs的单位是字节,所以10485761m700表示 700 个块。skip是要跳过的块数。因此,第一个dd将前 700*1048576 字节的repo.bundle写入repo.bundle1,第二个dd跳过前 700*1048576然后将其余字节写入repo.bundle2

将这两个文件传输到另一台计算机后,请使用cat将它们合并:

cat repo.bundle1 repo.bundle2 > repo.bundle

请注意,cat之后的文件顺序很重要。我们可以使用md5sum来检查组合repo.bundle是否与原点相同。如果两个文件仍然太大,我们可以将原始文件拆分为多个部分。小心每个ddskip

ddcatdumd5sum也有git-bash

相关内容

最新更新