Git浅克隆到特定标签

63
我想克隆Linux内核存储库,但只从版本3.0开始,因为内核存储库非常庞大,如果我能进行浅克隆,它会使我的版本控制工具运行更快。我的核心问题是:如何告诉git“--depth”参数的“n”值是多少?我希望这将起作用:

git clone http://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git --depth v3.0

谢谢。


1
请参考以下内容: 如何从Git仓库中删除旧的历史记录? - Alberto
6个回答

111

tag克隆到深度为1怎么样?

  • git clone --branch mytag0.1 --depth 1 https://example.com/my/repo.git

注:

  • --depth 1表示--single-branch,因此不会将其他分支的信息带入克隆的存储库。
  • 如果要克隆本地存储库,请使用file://而不是仅使用存储库路径。

16
不幸的是,“--branch”这个词有误导性,但正如手册所述,该参数也可以接受标签。显然这是正确的方法! - hackel
1
@chris-h 提示提示 ^^ ! - not2qubit

7
对于已经有克隆版本的人,这个命令将获取当前分支末端和标签“v5.2”之间的提交次数:
$ git rev-list HEAD ^v5.2 --count
407

我发现了这个使用GitHub API实现rev-list的项目: https://github.com/cjlarose/github-rev-list 关于rev-list,其官方文档非常长,说明了其背后有很多复杂的操作。可能会有许多不同的路径通过分支和合并来计算提交次数。但是,在这种情况下,可以忽略这些细节。

7
阅读完整的解决方案,但不幸的是,git clone不能按您要求的方式工作。参数--depth限制了revisions的数量,而不是commits的数量。没有一个克隆参数可以限制提交量。在您的情况下,即使您知道在v3.0和repo中最新的HEAD之间,文件中至多只有10个修订差异,并使用--depth 10,您仍然可以获得大部分或整个repo历史记录。因为有些对象可能没有达到10个修订,并且您将获得它们的历史记录,一直追溯到它们在repo中首次出现。
现在,这是如何做你想要的:
您的问题的关键在于您需要在v3.0和您想要的最近引用之间获取提交。以下是我执行的步骤:
- git clone http://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git --depth 10075 smaller_kernel_repo - cd smaller_kerenel_repo - 确定v3.0的sha git log --oneline v3.0^..v3.0 - 创建以此sha为起点的嫁接点(它是02f8c6aee8df3cdc935e9bdd4f2d020306035dbe) - echo "02f8c6aee8df3cdc935e9bdd4f2d020306035dbe" > .git/info/grafts - 为了解决一些内核日志条目的问题,请执行以下操作:export GIT_AUTHOR_NAME="tmp"export GIT_COMMITTER_NAME="tmp" - 有一个关于git filter-branch在跟随嫁接点重写历史的man页面上的良好警告...所以让我们滥用它,现在运行git filter-branch并坐等...(等待时间有点长)
现在您需要清理一切:
git reflog expire --expire=now --all
git repack -ad  # Remove dangling objects from packfiles
git prune       # Remove dangling loose objects

这个过程很耗时但不是非常复杂。希望从长远来看,它能为你节省你所期望的所有时间。此时,您将拥有一个修订历史记录仅包含自linux-stable.git repo的v3.0版本及以后的内容的存储库。就像在克隆时使用--depth一样,您的存储库也有相同的限制,并且只能从您已经拥有的历史记录中进行修改和发送补丁。虽然有一些方法可以解决这个问题,但这需要单独进行问答。
我正在测试最后几步,但是git filter-branch操作仍在进行中。如果出现任何问题,我将更新此帖子,但我将继续发布它,以便您如果认为可接受可以开始这个过程。
更新
解决问题(致命错误:空标识符<>不允许)。这个问题源于linux repo的提交历史记录中的问题。
git filter-branch命令更改为:
git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_EMAIL" = "" ];
    then
            GIT_AUTHOR_EMAIL="tmp@tmp";
            GIT_AUTHOR_NAME='tmp'
            GIT_COMMITTER_NAME='Me'
            GIT_COMMITTER_EMAIL='me@me.com'
            git commit-tree "$@";
    else
            git commit-tree "$@";
    fi '

7
在这里严格区分“修订”和“提交”会使事情变得过于复杂。虽然我知道它们之间的正式区别,但在git clone --depth <n>的上下文中,修订次数等于从顶部提交的次数。 - sschuberth

3
很遗憾,git clone--depth参数只接受数字,表示克隆仓库应截断的修订版本数。
一种可能的解决方案是克隆整个仓库,然后在保留v3.0之后的提交时截断其历史记录。以下是一个好的操作指南:http://bogdan.org.ua/2011/03/28/how-to-truncate-git-history-sample-script-included.html
git checkout --orphan temp v3.0
git commit -m "Truncated history"
git rebase --onto temp v3.0 master
git branch -D temp
git gc

1
这应该和我提供的解决方案一样有效,但我建议删除所有其他本地引用并运行我解决方案中的清理步骤。否则,仓库仍将包含完整的历史记录和额外的对象。对于这个仓库来说,会有大约200万个不必要的对象挂在那里。 - James
1
这种策略需要管理冲突合并,并且存在风险,取决于如何处理合并,可能会产生不完全与最终主分支的副本。由于仓库非常大,很难手动进行合并,因此可以在rebase命令中添加“-Xours”或“-Xtheirs”选项。我相信你会发现最终结果与主分支引用源有所不同。 - James

0

--depth 参数似乎只是一个数字(“指定的修订版本数量”),而不是标签。

可能的思路(需测试):

您可以尝试使用 git describe 命令,以获取当前 HEAD 中最新的标签,以及该标签和 HEAD 之间的提交次数。
如果这个“最近的标签”不是您想要的标签,则可以重复此过程,从最新标签所引用的提交开始,直到找到您的标签(例如,您的标签为 v3.0)。

所有这些提交编号的总和将为您提供在 git clone 命令中要使用的深度,前提是您的标签可从您的当前 HEAD 访问。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接