只将最新提交拉到浅层克隆

时间:2017-09-05 05:53:31

标签: git merge clone pull

我已经看到很多关于融入浅层拉动的问题,但大多数似乎已经过时了,而其他人则不清楚。

我们的git存储库历史非常庞大。这是由于过去一些错误的大量文件提交造成的(这些文件已被删除)。 执行完整克隆需要永远,因为它会提取这些文件,然后才删除它们。它还会在计算机上生成一个巨大的.git目录。

为了解决这个问题,我们进行了深度为1的浅层克隆。 这一切都很好,我们能够工作和提交并合并回主人。 但是,如果主人有变化,那么我需要将他们拉进我的分支。这是问题开始的地方。 现在拉回来并像完整克隆一样获取主人的所有历史记录。 我需要的只是自上次拉动以来的变化。

那么,有什么方法可以告诉它这样做吗? 深度为1的另一次拉动会解决我的问题吗?

我正在处理的分支是一项特殊功能,需要一些时间才能完成,因此它将运行" parallel"在合并之前已经有一段时间了。 拉深度1会使我的分支与主人断开连接,从而阻止我合并回来吗?

1 个答案:

答案 0 :(得分:2)

不要考虑pull;这就像试图揉你的肚子同时轻拍你的头。它可以完成,但在掌握每一半之后最好完成。 :-)所以,把它分解成它的组成部分:

  1. fetch
  2. merge
  3. 现在,记住clone基本上是init + remote add + fetch + checkout,我们可以看到 clone实际上是一个浅层 fetch

    这意味着您要将步骤1 fetch修改为浅。

    到目前为止,这没什么大不了的,但现在我们进入第2步merge。合并需要一定的深度。但是 - 多少深度?那么,这就是我们解决问题的原因。所需的深度取决于图中的节点,而获取节点,我们必须获取它们。暂时假设我们已经足够了#34;其中很多是:我们现在有一个如下图:

    ...--o--*--o--o   <-- yourbranch (HEAD)
             \
              o--o--o   <-- other
    

    other的{​​{1}}参数,通常是远程跟踪分支名称,如git merge other,指定您要合并的其他一些提交。 Git需要您的分支提示提交(origin/master节点,o,例如yourbranch,指向),他们的分支提示提交,以及我用master标记的合并基础提交。

    对于Git来找到合并基础,并证明Git满意这个合并基础,Git需要之间的所有提交*和每个分支提示(包括*本身)。

    这是多少?那么,这取决于实际的图表。我们绘制了一个图表,其顶线 - 您的分支 - 需要三个:尖端,从尖端返回的第一步,以及从尖端返回的第二步。我们的底线需要四个:尖端,从尖端向后两步,再往后一步到达*

    因此,对于图表,所需的*将为4,因为3和4中的较大者为4。

    您的图表需要多少?那么,这取决于你的图表!事先没有说明:在你有足够的图表来确定你是否有足够的图表之前,你没有足够的图表。一旦你有足够的图表,你就可以找到合并基础,然后计算&#34;最深的行&#34;。

    请注意,我们绘制了一个非常简单的图表。它可能更复杂,例如:

    --depth

    要查找此图表的最小深度,请将...--o--*--o--...--o <-- yours (HEAD) \ \ o--o--o \ / \ o--o o--o <-- other \ / o-----o 顶部的直线追溯到yours,并在底部跟踪两条线*返回other。 (显然,底部分割的上半部分将是较长的线,所以我们可能有点懒,只计算那些节点。)

    在何处进行此计数

    现在问题显而易见了:为了重新计算(包括)合并库,我们必须找到合并库,这意味着我们需要足够的深度才能能够< / em>找到合并基础。

    不幸的是,我们必须在具有所有提交的存储库中执行此操作,并且您已在存储库中创建了不在其他存储库中的新提交。如果我们可以将您的提交推送到主存储库并在那里完成工作,那将很容易。

    (我们实际上不必一次得到所有的计数。只需要得到&#34;你的数量&#34;以及&#34;他们的数量&#34;并且取这两者中的较大者细节变得有点粘;如果你想这样做,我会让你解决它。考虑合并基础是否包含在你迄今为止获得的子图中;这些是你必须实施的两种情况。)

    然后,一个解决方案就是这样做:将您的提交推送到已经包含其他所有内容的存储库。 (有关此操作的约束,请参阅VonC对Why can't I push from a shallow clone?的回答。)为此,您需要在该保留的更完整克隆上写入名称你做这种操作。例如,您可以拥有保留的分支或标记名称*或其他类似名称:

    for-blitz-count-trick

    然后让git push $remote HEAD:for-blitz-count-trick 的Git计算合并基数并计算提交。然后只需完全删除名称$remote,这样您就可以在下次再次执行此操作时做好准备。

    我们暂时假设您计划运行for-blitz-count-trick,以便git merge $remote/other上的名称为$remote,并且您已完成此特殊推送。您现在登录other,在那里可以计算出正确的$remote

    如果您愿意以相当大的余量超调,则命令序列:

    --depth

    应该做的。

    我实际上没有测试过这个,但它都是基于明显的图形操作。对于像我展示的更复杂的图形这样的情况,它会计算所有fork-and-join序列上的所有节点,这就是为什么它存在过度计数的风险。我使用base=$(git merge-base for-blitz-count-trick other) git rev-list --count --ancestry-path $base^@..for-blitz-count-trick git rev-list --count --ancestry-path $base^@..other 包含提交$base^@,同时排除其父项。还值得注意的是,如果没有公共合并库,或者如果存在多个合并库,则此方法将失败,因此检查是否只有一个合并库可能是个好主意。

    我不认为$base可以与--ancestry-path结合使用,但类似命令:

    --left-right

    也应该有效,在某些情况下存在过度计算边界提交的风险,因为git rev-list --count --left-right --boundary for-blitz-count-trick...other 实施得很糟糕。这个不会失败存在多个合并基础,并且在一个命令中得到两个计数,所以它可能是实践中的方式。

    如果那不可能(或者甚至太烦人)

    可能是您无法登录--boundary来执行此项工作,或某些策略阻止在那里创建临时名称,或两者兼而有之。在这种情况下,您可以简单地重复增加克隆深度,直到找到合并基础,或者完全取消对您的克隆进行非浅化(当且仅当没有合并基础时才会发生后者)。

    从根本上说,问题是你需要足够的深度来计算多少深度就足够了。一旦你拥有那个深度,你就可以重新浅薄了#34;确切的数字,无论它是什么,但没有真正指向这个&#34;重新变浅&#34;。随着存储库本身通过添加新提交而增长,所需的$remote也会增长,但是如果您的工作被反复合并(并推送),则会缩小所需的--depth

    实际上,它可能足以一次添加50个,直到你有足够的深度,然后保持在那个深度,无论它是什么,直到它证明太浅;然后增加它。请注意,您需要在某处自己存储此号码:请参阅how to know the depth of a git's shallow clone?

    因此,丑陋但实用的方法:只需选择一些有用的深度,并使用它直到它不起作用,然后增加它。永远不要运行--depth,只需将其分解为git pull和其他命令(通常为git fetch,但git merge也可以)。