【问题标题】:Git find modified files since <ref> from a shallow cloneGit 从浅克隆中查找自 <ref> 以来修改过的文件
【发布时间】:2017-10-03 06:47:12
【问题描述】:

我在一个 CI 盒子上运行测试。为了加快速度,我只是在做一个浅克隆:

git clone --depth 1 git@github.com:JoshCheek/some_repo.git

假设所有测试都通过了,我想触发管道中的下一步。触发什么取决于上次d部署(参考d123456)和我刚刚测试的c当前参考(参考c123456)之间更改的文件。如果我做了一个正常的克隆,我可以这样发现:

git diff --name-only d123456 c123456

但是我的克隆很浅,所以它不知道那些提交。我看到我可以使用git fetch --depth=n 来获取更多的历史,但我只知道SHA,不知道SHA 的深度。下面是一组大概可以回答这个问题的方法:

# hypothetical remote diff
git diff --name-only origin/d123456 origin/c123456

# hypothetical ref based fetch
git fetch --shallow-through d123456
git diff --name-only d123456 c123456

# hypothetical way to find the depth I need
depth=`git remote depth-to d123456`
git fetch --depth "$depth"
git diff --name-only d123456 c123456

否则,我可能不得不编写一个循环并继续调用--deepen,直到我的历史记录包含提交。这看起来很痛苦(意味着编写/维护很烦人)和昂贵的(意味着慢,记住浅克隆的目的是降低这个成本)。

【问题讨论】:

    标签: git git-diff git-remote git-fetch


    【解决方案1】:

    否则,我可能不得不编写一个循环并继续调用--deepen,直到我的历史记录包含提交。这似乎很痛苦......

    痛苦的(而且很慢,你稍后会注意到)。

    现代 Git(自 2.11 版起)确实有一个新的git fetch 选项:

    --shallow-exclude=

      加深或缩短浅层存储库的历史,以 排除可从指定的远程分支或标签访问的提交。 该选项可以指定多次。

    这个我没试过;目前尚不清楚它是否允许哈希 ID(测试使用名称),并且在任何情况下,您都将指定要深化的提交的 parent(s),而不是您想要的提交获得。但这可能就足够了。

    (我真的认为更好的方法是保留可以借用的参考克隆。)

    【讨论】:

    • 哦,不错,我完全错过了!可悲的是,似乎 Github 不支持它,当我尝试时它说 fatal: Server does not support --shallow-exclude :(
    • 你能详细介绍一下最后一个注释吗?我不清楚参考克隆是什么(您是说缓存在 CI 服务器上的完全克隆的存储库吗?)。
    • 是的:使用参考克隆,您运行git clone --reference &lt;path&gt; [options] &lt;url&gt;,Git 像往常一样在 URL 处调用另一个 Git,然后从参考克隆中借用或复制(参见 --dissociate)对象而不是通过网络复制它们。在一个真实项目上测量,我使用参考克隆将克隆挂钟时间从近两个小时缩短到几分钟。 (这涉及到一些相当大的存储库。)
    • 谢谢,我将尝试保留一个缓存的克隆,到目前为止它看起来很有希望。
    • 2021 年更新:Github 现在支持浅排除,但您不能使用提交哈希作为参数(如果您尝试,则会收到错误“远程端意外挂断”)
    【解决方案2】:

    除了浅克隆之外,还有几种可能的解决方案可以减少克隆时间和空间。

    1.git clone &lt;url&gt; -b &lt;branch&gt; --single-branch

    这只会获取&lt;branch&gt; 可访问的数据。不如--depth=1 有效,但仍比完整克隆好。当 repo 有许多不同的分支时,它可以正常工作。

    2.git init;git fetch &lt;url&gt; &lt;tag&gt;

    同样,它只获取&lt;tag&gt; 可访问的数据。

    3.创建并使用镜像仓库。

    git clone &lt;url&gt; --mirror -- /foo/mirror/foo/mirror 是镜像仓库。假设您的 CI 系统同时启动多个实例。通过git clone &lt;url&gt; --reference=/foo/mirror -- &lt;instanceN&gt; 克隆每个。在每个克隆中,只会从远程仓库下载镜像仓库中找不到的数据。您可以在作业完成后删除实例以节省空间。但是只需根据远程仓库的更新频率定期通过git fetch 保存和更新镜像仓库。例如,每天半夜一次,或者每周一次的周日。

    4.使用git worktree

    创建一个克隆,保留它并在每个 CI 实例启动时首先更新它。使用git worktree 将修订签入每个实例的不同工作树中。

    【讨论】:

    • 感谢您的建议!我最终将使用缓存的克隆。可能需要在这里使用其他人的一些想法,如果它的状态变得不稳定,但我现在充满希望。
    【解决方案3】:

    我遇到了同样的问题并使用了这个

    git clone --shallow-since=&lt;date&gt;

    我不仅要存储我上次部署的 SHA,还要存储我上次部署的日期,否则效果很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 2019-08-11
      • 2013-10-21
      • 2016-10-25
      • 1970-01-01
      • 2020-06-26
      相关资源
      最近更新 更多