仅获取基本分支中不存在的提交范围

时间:2019-01-14 12:51:12

标签: git github

我只想仅提取在其基础branchA中不存在的branchB提交。

例如,考虑以下历史记录:

B1 - B2 - B3 - B4 - B5
           \
            A1 - A2 - A3

我只想获取 A1A2A3。 需要特别注意的是,我不知道哪个提交是A1,以及我需要获取多少个提交。 我的输入只是两个分支的负责人, 在此示例中,branchA=A3branchB=B5。 基于这样的输入,我需要标识A1并获取A1branchA之间的所有内容,理想情况下仅此而已。

或者,获取包含A1A2A3的最小提交集以及足以标识A1的信息也很有趣。

为什么?在我只需要那些提交的用例中(“ branchA中相对于branchB的更改),获取比必要提交更多的内容会减慢我的处理速度,例如,一个大型的存储库,其中包含数千个提交,而功能分支仅包含少量提交。获取branchAbranchB的整个历史记录会获取很多我不需要的提交,并且会花费大量时间和网络带宽。

我想出了一个丑陋的技巧,通过从浅克隆开始,逐步获取越来越多的数据,直到找到一个共同的提交,从而避免获取完整的历史记录:

git clone --depth 1 "$repo" --branch "$branchA" shallow
cd shallow

for ((depth = 8; depth <= 1024; depth *= 2)); do
    echo "trying depth $depth ..."
    git fetch --depth $depth
    git fetch --depth $depth origin "$branchB:$branchB"
    lastrev=$(git rev-list --reverse "$branchB" | head -n1)
    if git merge-base --is-ancestor "$lastrev" HEAD; then
        echo "found with depth=$depth"
        break
    fi
done

这适用于我的用例:它获取足够大的提交子集以标识A1并包含提交,直到branchA的开头,并且比获取两个分支的完整历史记录要快

有没有比这更好的方法了?我正在寻找一个纯粹的Git解决方案,但是如果GitHub API可以使它变得更快,更容易,那也很有趣。

1 个答案:

答案 0 :(得分:1)

今天这不可能。变通办法的变种是您所能做的最好的。

协议中没有什么可以阻止您向--depth提供原始哈希ID而不是git fetch参数,而不会告诉git fetch假装< / em>提供了正确 --depth(无论是什么)。但是git fetch中也没有任何东西可以实现这一点。因此,执行此操作的唯一方法是从每个分支提示中一次枚举一次提交,直到找到正确的哈希为止,该哈希还告诉您--depth参数应为{ {1}}命令。

但是,在大多数情况下,当您遍历足够的哈希ID以找到正确的深度时,您可能已经完成了完整克隆。因此,在外部 Git中实现此功能的压力很小(例如,通过GitHub接口)。而且,通过哈希ID命名提交对于人类来说根本不是一件有趣的事,因此(或感觉)将此功能添加到git fetch的压力也很小。

最好的解决方案是,您可以向另一个Git存储库提供起始哈希(您自己的Git可以通过本地名称到哈希的转换提供):他们的git fetch分支的尖端是B,以便您自己的B4标识提交origin/B,您可以在本地运行(请注意,拟议的B4参数今天不存在):

--depth-inferred-from

拥有您的Git:

  1. 运行git fetch --depth-inferred-from=origin/B A ,或与之等效的git ls-remote始终运行
  2. 将他们的git fetch(您打算提取)转换为哈希ID,在步骤3中表示为refs/heads/A
  3. 要求他们的Git在进行 have 会话期间提交提交时仅枚举H
  4. 进入正常提取的其余部分,即用于获取要提取的对象ID的have / want会话

但是,第3步在获取协议中需要一个新功能,因此非常简单。