我已经看到很多关于融入浅层拉动的问题,但大多数似乎已经过时了,而其他人则不清楚。
我们的git存储库历史非常庞大。这是由于过去一些错误的大量文件提交造成的(这些文件已被删除)。 执行完整克隆需要永远,因为它会提取这些文件,然后才删除它们。它还会在计算机上生成一个巨大的.git目录。
为了解决这个问题,我们进行了深度为1的浅层克隆。 这一切都很好,我们能够工作和提交并合并回主人。 但是,如果主人有变化,那么我需要将他们拉进我的分支。这是问题开始的地方。 现在拉回来并像完整克隆一样获取主人的所有历史记录。 我需要的只是自上次拉动以来的变化。
那么,有什么方法可以告诉它这样做吗? 深度为1的另一次拉动会解决我的问题吗?
我正在处理的分支是一项特殊功能,需要一些时间才能完成,因此它将运行" parallel"在合并之前已经有一段时间了。 拉深度1会使我的分支与主人断开连接,从而阻止我合并回来吗?
答案 0 :(得分:2)
不要考虑pull
;这就像试图揉你的肚子同时轻拍你的头。它可以完成,但在掌握每一半之后最好完成。 :-)所以,把它分解成它的组成部分:
fetch
merge
现在,记住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
也可以)。