【问题标题】:git shallow clone to specific taggit浅克隆到特定标签
【发布时间】:2012-01-19 19:53:26
【问题描述】:

我想克隆 Linux 内核存储库,但只能从 3.0 版开始,因为内核存储库非常庞大,如果我可以进行浅克隆,我的版本控制工具运行速度会更快。我的问题的核心是:如何告诉 git --depth 参数的“n”值是什么?我希望这会奏效:

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

谢谢。

【问题讨论】:

标签: git


【解决方案1】:

如何将标签克隆到深度为 1?

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

注意事项:

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

【讨论】:

  • 不幸的是,“--branch”具有误导性,但正如手册所述,此参数也可以接受标签。这显然是要走的路!
  • @chris-h 提示提示 ^^ !
【解决方案2】:

阅读完整的解决方案,但不幸的是, git clone 不能按照您要求的方式工作。 --depth 参数限制revisions 的数量而不是commits 的数量。没有限制提交数量的克隆参数。在您的情况下,即使您知道与 repo 中 v3.0 和最新 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 通过遵循移植点重写历史......所以让我们滥用它,现在运行 git filter-branch 并坐下来等待......(等待然后等待)

现在你需要清理所有东西:

git reflog expire --expire=now --all
git repack -ad  # Remove dangling objects from packfiles
git prune       # Remove dangling loose objects

这个过程很耗时,但不是很复杂。从长远来看,希望它能为您节省所有您希望的时间。此时,您将拥有一个实质上是一个 repo,其历史仅从 linux-stable.git repo 开始修改为 v3.0。就像在克隆上使用 --depth 一样,您对 repo 有相同的限制,并且只能从您已有的历史记录中修改和发送补丁。有很多方法可以解决这个问题。但它值得自己的问答。

我自己正在测试最后几个步骤,但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 '

【讨论】:

  • 我认为在这里严格区分 revisioncommit 过于复杂。虽然我知道the formal difference,但在git clone --depth <n> 的上下文中,修订数等于提示中的提交数。
【解决方案3】:

对于已经有克隆的人,此命令将获取当前分支的尖端和标签 5.6 之间的提交次数:

$ git rev-list HEAD ^5.6 --count
407

我发现这个项目使用 GitHub API 实现了 rev-list: https://github.com/cjlarose/github-rev-list

rev-list 上非常冗长的手册页表明幕后发生了很多事情。有许多不同的路径可以通过分支和合并来计算提交。对于这个用例,虽然这可能会被忽略(?)

【讨论】:

    【解决方案4】:

    不幸的是,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
    

    【讨论】:

    • 这应该和我提供的解决方案一样有效,但我也建议删除所有其他本地引用并运行我在解决方案中的清理步骤。没有它,repo 仍将包含完整的历史记录和额外的对象。有了这个 repo,大约需要 200 万个对象。
    • 此策略需要管理冲突的合并,并且可能会根据合并的处理方式生成最终主副本的不完全副本。由于 repo 太大,您不太可能手动进行合并,因此您可以将 -Xours-Xtheirs 选项添加到 rebase 命令。我相信您会发现最终结果与主参考的来源不同。
    【解决方案5】:

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

    可能的想法(待测试):

    您可以使用git describe 从您当前的 HEAD 获取最新标签,以及所述标签和 HEAD 之间的提交次数。
    如果该“最新标签”不是您的标签,只需重复该过程,从该最新标签引用的提交开始,直到找到您的标签(例如,v3.0)。

    所有这些提交数的总和将为您提供git clone 命令的深度,前提是您的标签可以从您当前的HEAD 访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      相关资源
      最近更新 更多