有没有办法拆分 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
提交将放置在此捆绑包中。
看起来D
、E
、F
是下一个合乎逻辑的步骤;但F
取决于brnach2
中提交o
。 因此,下一个合乎逻辑的事情实际上是将branch2
与D
捆绑在一起。 既然我们还有master
C
我们可以说
git bundle create 2.bundle master..branch2
现在我们需要将master
移动到G
,以便我们可以捆绑E
、F
和G
。 确保我们在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建议使用dd
和cat
相比,上述方法有利有弊。
它只依赖于 git 本身(尽管dd
/cat
方法所需的实用程序通常随 git 一起提供)。
各个捆绑包文件本身都很有用,而如果您使用dd
对文件进行分段,则必须重建所有部件以确保您有一个可用的捆绑包。 这也意味着您可以保存捆绑包并将它们与您以后创建的其他捆绑包组合(随着更多更改的发生);但是,仅当您需要从头开始创建另一个新的远程存储库时,这才有意义。
实际上,只是来回发布增量更改,其中双方已经有一个共同的提交基线,是捆绑包的基本用例。 因此,您可能决定使用dd
/cat
方法最初创建远程存储库,然后使用增量捆绑包进行后续更新共享。
dd
/cat
方法的最大优点是它非常死记硬背/可编写脚本(即假设工具在手边很简单),而你必须考虑如何为上述方法划分提交;而且dd
方法可以拆分单个令人讨厌的大提交,如果结果是一个。
我最初也忘了提到,您可以列出要包含在捆绑包中的多个分支。 因此,例如,如果您的阈值更像是每个捆绑包 8 次提交,您可以
1) 将master
移至E
2) 捆绑master
,branch1
为 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
的单位是字节,所以1048576
是1m
。700
表示 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
是否与原点相同。如果两个文件仍然太大,我们可以将原始文件拆分为多个部分。小心每个dd
的skip
。
dd
、cat
、du
、md5sum
也有git-bash
。