Git 是否可以从远程下载指定提交的单个文件?

Git 是否可以从远程下载指定提交的单个文件?,git,Git,我正在尝试从远程中的特定提交中签出特定文件 请注意,提交不在本地repo中,只是远程repo的一部分 我不想从GitHub/bitbucket接口下载原始文件。因为我的遥控器不在类似的平台上 我不想先做git fetch,然后再做git checkout,因为做git fetch会下载一堆我不想要的其他项目。我只对特定提交中的特定文件感兴趣 如果您碰巧知道包含此提交的特定远程分支,则可以单独获取此分支: git fetch origin some_branch 然后,在您想要的确切提交位置

我正在尝试从远程中的特定提交中签出特定文件

请注意,提交不在本地repo中,只是远程repo的一部分

  • 我不想从GitHub/bitbucket接口下载原始文件。因为我的遥控器不在类似的平台上

  • 我不想先做git fetch,然后再做git checkout,因为做git fetch会下载一堆我不想要的其他项目。我只对特定提交中的特定文件感兴趣


  • 如果您碰巧知道包含此提交的特定远程分支,则可以单独获取此分支:

    git fetch origin some_branch
    
    然后,在您想要的确切提交位置签出文件:

    git checkout abc123 -- path/to/your/file.ext
    

    不幸的是,你不能做你在问题和评论中描述的事情

    git
    不能像
    subversion
    或其他源代码管理系统那样在文件级别工作
    git
    在快照级别工作。
    de(这是git工作原理的一个非常简单的模型,在引擎盖下更复杂)。因此,获得所需文件的唯一方法是

    • 首先从服务器向本地计算机获取快照(
      git fetch
    • 其次,一旦有了快照,就可以从快照中提取文件(
      git checkout
    演示如何执行此操作。

    编辑:来自评论:

    我需要从分布在十几个分支上的数百个提交中检查同一个文件

    为此,您需要其他回购协议管理员的合作

    在Git中,历史是通过给它一个refname(分支、标记等)和通过共享文件系统或托管服务器的某种访问来发布的

    不值得给出自己的refname的东西要么是已发布历史的一部分(有自己的refname),要么不是

    如果是的话,Git将确保您获得一个完整的、内部一致的包,该包将为您提供所需的已发布历史的最新信息。Git的激光器致力于使特定操作尽可能快速高效

    如果不是,那么托管回购协议没有发布它,(a)你通常根本无法获得它,(b)你通常甚至不知道如何请求它,它的对象id

    要找到一个对象的id,您必须搜索历史记录并检查快照。。。这意味着你必须有快照。。。看到了吗

    Git不喜欢支付两次管理费用,而且它是为风投而建的。您正试图像使用共享文件系统一样使用它。构建文件系统是为了能够高效地将单个对象频繁重复地提供给同一客户机。DVC的构建是为了高效地服务于多个完整的修订版本,在相对较长的时间间隔内,每个客户一次。这是一个工程权衡的领域:你不可能在这两方面都非常高效,而且你在其中一方面做得越好,就越难重新使用工具并做其他事情

    所有这些都表明:如果你能让其他回购管理员为你做一些定制工作,这并不难:

    git rev-list --branches --objects -- path/to/file | git pack-objects pack
    
    将打包该文件的所有分支版本的历史记录:引入新版本的提交、显示其位置的树及其内容,并将其放入名为
    pack-.{idx,pack}
    的两个文件中。把这个包放在任何repo的
    objects/pack
    目录中,你就在那里:你已经得到了处理这个文件所需要的一切

    这样一段分割的历史相对来说比较难处理,而按需填充缺失部分的开销正是Git所要避免的,但使用的正是您所拥有的,您可以使用例如
    git verify pack-v
    向您显示包的确切内容,并使用
    git cat file-p
    打印单个对象。该包中的提交是引入新版本的提交,您可以通过在提交id中附加
    :path/to/file
    来引用其中一个版本中的文件

    因此,当您运行verify包查看您得到了什么时,您将得到大量关于其内容和结构的waaayyyy信息。为了使它对您的目的有用,您可以只提取提交ID,并按日期顺序列出这些ID,使用

    # this is the pack I made for testing 
    git verify-pack -v .git/objects/pack/pack-8d3bb7bca6a4cdc086778ad55c79f45e672ae7e5.idx \
    | awk '$2=="commit"{print $1}' \
    | git rev-list --stdin --date-order --no-walk
    
    log
    中为
    rev list
    添加子项,以查看日志消息,或者您可以显示用git show:path/to/file获取的blob。要按时间顺序显示BLOB,可以

    git     git verify-pack -v .git/objects/pack/pack-8d3bb7bca6a4cdc086778ad55c79f45e672ae7e5.idx \
    | awk '$2=="commit"{print $1}' \
    | git rev-list --stdin --date-order --no-walk --pretty=%h:path/to/file \
    | git cat-file --batch
    
    它将以可扫描的形式转储内容

    。事实上,如果一个历史记录的多功能转储就可以了,并且您只需要匹配内容和序列,而不是结果提交id,那么您可能需要一个管理员来完成这项工作

    git fast-export --branches -- path/to/file | zstd >my-stuff.zst
    
    它甚至可能比包文件更紧凑(因为它不必保留id),并将其发送给您

    我不想先做git fetch,然后再做git checkout,因为做git fetch会下载一堆我不想要的其他项目

    您需要执行
    git fetch
    。这就是让远程服务器向您发送内容的方式。但是,您可以使用以下方法最小化它发送给您的“额外内容”的数量

    git fetch --force --depth 1 origin $COMMIT_SHA:tmp
    
    这将从远程
    源站
    获取commit
    $commit\u SHA
    (以及完成它所需的所有文件-好吧,你无法避免),并将其命名为
    tmp
    。如果名为
    tmp
    的分支已经存在,则
    --force
    将防止故障(适合重复使用,但使用时务必小心)

    然后您可以
    git cat file blob tmp:somepath
    git checkout tmp--somepath
    或任何您想要访问文件内容的内容


    如果您
    git分支-D tmp;git gc
    完成后,实际上应该没有累积积垢。

    如果服务器端配置未启用,则可能无法工作
    git archive --remote=<url_to_the_repo> <commit> --format=tar <path> | tar xvf -