代码之家  ›  专栏  ›  技术社区  ›  Max Leske Thomas Shelby

如何打开打包的参考文件?

  •  16
  • Max Leske Thomas Shelby  · 技术社区  · 16 年前

    我从Github克隆了一个项目 Git克隆--镜像 . 这让我有了一个存储库, 包装参考品 文件,一个 包装 和一个 IDX 文件。为了开发的目的,我想查看松散的对象,所以我用 Git解包对象<<pack file> 这很好(如果你想知道的话,我把包文件解包到一个新的repo中)。唯一的问题是 裁判/指挥部/ 仍然是空的,所有引用仍仅在 包装参考品 但我需要他们 裁判/指挥部/ . 我找不到一个可以提取或解包这些引用的命令,并且不知何故我不相信必须手工(或通过管道)完成这项工作。

    所以实际上我有两个问题:

    1. 是否有一种简单的方法可以从 包装参考品 ?
    2. 如果没有,为什么没有呢?如果有一个解包对象的命令,那么不为refs提供这个命令的原因是什么(不要忘记甚至有一个命令 Git包参考 ……)

    谢谢你的建议和建议。

    4 回复  |  直到 8 年前
        1
  •  29
  •   clee nortron    12 年前

    简短的回答是“不”——没有“简单的方法”可以像你要求的那样打开参考文件。

    稍微长一点的答案是,每个引用只是一个特定路径中的41字节文本文件(40字节sha1,十六进制+换行),所以“硬”版本只需要在您的 ~/.gitconfig :

    [alias]
    unpack-refs = "!bash -c 'IFS=$''\\n''; for f in $(git show-ref --heads); do /bin/echo ''Writing  '' $(echo $f | cut -c42-); echo $(echo $f | cut -c1-40) > \"${GIT_DIR:-.git}/$(echo $f | cut -c42-)\"; done'"
    

    花了点小技巧来弄清楚如何让它正常工作,但现在你走了!现在你有了“git unpack refs”,它可以做你期望的事情,作为奖励,如果设置了这个选项,它甚至可以和$git_dir一起工作(否则它假设你在git树的根目录中)。如果你还没有读到Git别名, https://git.wiki.kernel.org/index.php/Aliases 是一个很好的引用,甚至包括一个示例“git alias”扩展,您可以使用它来扩展自己的别名。

        2
  •  13
  •   Cascabel    16 年前

    压缩的ref s存在的原因是为了加快在一个有无数ref s的repo中的访问速度-查看一个具有多行的单个文件比对每个引用只访问一次文件系统要容易得多。Git中任何需要了解ref s的内容都会通过代码读取ref s目录和压缩的ref s文件。打开包装会破坏它的目的。如果要访问参考,请使用管道命令(例如,显示参考,对于每个参考,更新参考…)。我真的想不出任何一种访问方式,在目录结构中比在管道命令(特别是对于每个可用的引用)中更快更容易。

    是的,打包的对象(如打包的refs)是为了提高性能而创建的,但是有很大的区别。压缩的refs文件只是一堆独立的行。基本上,你可以免费添加或删除它。不需要解包来修改它。另一方面,打包的对象是增量压缩的,因此内部的对象相互依赖。它们极大地减少了磁盘使用量,并且可以以合理的成本从中读取对象,但是尝试修改包中的对象集比修改松散对象要昂贵得多,因此只能通过 git repack (由 git gc 尽管我不相信 重装 实际上,解包对象——它只是从packfile中读取它们,用松散的对象打包,并生成一个新的包。

    但是,当一个包从远程传输时,它会在本地端解包。我看到在 git receive-pack 源,以及 pack-objects 曼佩尔说:

    git unpack objects命令可以读取打包的存档文件,并将包中包含的对象扩展为“一个文件一个对象”格式;这通常是在动态创建包时由智能拉命令完成的,以便对等端高效地进行网络传输。

        3
  •  2
  •   Schlacki    9 年前

    你的问题1的另一个答案是:

    我假设您已经使用了这样的循环来使用git unpack对象:

     mkdir CLONE
     mv .git/objects/pack/* CLONE/
     for pack in CLONE/*.pack; do
        git unpack-objects < $pack
     done
     rm -rf CLONE/
    

    它将解包所有对象,但将打包的分支头留在文件.git/packed-refs中

    由于我在这里重复使用了克莱的回答,我发现需要以下命令来解包分支头并进行清理:

    (
       IFS=$'\n'; # set the input field separator to new line
       for f in $(git show-ref --heads); do
          ref_hash="$(echo $f | cut -c1-40)"
          ref_label="$(echo $f | cut -c42-)"
          echo " unpack: $ref_hash $ref_label"
          echo "$ref_hash" > ".git/$ref_label";
          sed -i "s~^${ref_hash} ${ref_label}\$~~" .git/packed-refs
          sed -i '/^$/d'                           .git/packed-refs
       done
       rm .git/info/refs
       rm .git/objects/info/packs
    )
    

    注意克莱答案的不同之处:

    a)从.git/packed refs文件中删除压缩的refs,以及

    b)删除文件.git/info/refs和.git/objects/info/packs。

    我承认删除.git文件夹中的文件可能不是一个好主意,但是这是我需要做的,以便进行一个干净的解包。

    但问题2仍未得到回答。

        4
  •  0
  •   codeplay    8 年前

    我有一个解决方法,可能对你们中的一些人有用:

    基本上,在本地删除所有标记(将其从打包的引用中删除),然后再次获取它。

    git tag | xargs git tag -d && git fetch --tags