kbr*_*bro 51 git git-show git-rev-list
是否有比做库得到SHA1s的原始列表中的所有对象的一种更好的方式ls .git/objects/??/\*和cat .git/objects/pack/*.idx | git show-index?
我知道,git rev-list --all但只列出.git/refs引用的提交对象,我正在寻找包括由git-hash-object,git-mktree等创建的未引用对象的所有内容.
seh*_*ehe 36
尝试
 git rev-list --objects --all
编辑 Josh提出了一个很好的观点:
 git rev-list --objects -g --no-walk --all
列表对象可从ref-logs中获取.
要查看无法访问的提交中的所有对象:
 git rev-list --objects --no-walk \
      $(git fsck --unreachable |
        grep '^unreachable commit' |
        cut -d' ' -f3)
把它们放在一起,真正得到输出格式的所有对象rev-list --objects,你需要类似的东西
{
    git rev-list --objects --all
    git rev-list --objects -g --no-walk --all
    git rev-list --objects --no-walk \
        $(git fsck --unreachable |
          grep '^unreachable commit' |
          cut -d' ' -f3)
} | sort | uniq
要以稍微有用的方式对输出进行排序(通过树/ blob的路径,首先提交),请使用另一个| sort -k2对相同路径的所有不同blob(修订版)进行分组.
小智 26
我不知道这个选项何时存在,但你可以
git cat-file --batch-check --batch-all-objects
根据手册页,这给了你
存储库中的所有对象和任何备用对象存储(不仅仅是可到达的对象)
(强调我的).
默认情况下,这会产生对象类型及其大小以及每个哈希值,但您可以轻松删除此信息,例如使用
git cat-file --batch-check --batch-all-objects | cut -d' ' -f1
或者通过提供自定义格式--batch-check.
Ari*_*zis 10
从Mark和willkill的回答中,这是一个更正确,更简单,更快速的脚本再现.
它用于rev-parse --git-path查找objects目录,即使在更复杂的Git存储库设置中(例如,在多工作树情况下或诸如此类).
它避免了所有不必要的使用find,grep,perl,sed.
即使您没有松散的物体或没有包装(或者如果您倾向于在新的存储库上运行它),也可以优雅地工作.
然而,它确实需要从这个千年开始的Bash(2.02或者更新,特别是这个extglob位).
分享和享受.
#!/bin/bash
set -e
shopt -s nullglob extglob
cd "`git rev-parse --git-path objects`"
# packed objects
for p in pack/pack-*([0-9a-f]).idx ; do
    git show-index < $p | cut -f 2 -d ' '
done
# loose objects
for o in [0-9a-f][0-9a-f]/*([0-9a-f]) ; do
    echo ${o/\/}
done
经过一些修改后,Mark的回答对我有用:
grep -v代替--git-dir支持裸回购--show-cdup因为OS X山狮的BSD风格的perl不支持sed#!/bin/sh
set -e
cd "$(git rev-parse --git-dir)"
# Find all the objects that are in packs:
find objects/pack -name 'pack-*.idx' | while read p ; do
    git show-index < $p | cut -f 2 -d ' '
done
# And now find all loose objects:
find objects/ \
    | egrep '[0-9a-f]{38}' \
    | grep -v /pack/ \
    | perl -pe 's:^.*([0-9a-f][0-9a-f])/([0-9a-f]{38}):\1\2:' \
;
Erki Der Loony的答案中git cat-file --batch-check --batch-all-objects建议的命令可以通过新的Git 2.19(Q3 2018)选项更快地执行。--unordered
该API会迭代所有学习到的对象,以便有选择地按照对象在packfiles中出现的顺序列出对象,如果在枚举对象时调用方访问这些对象,则可以帮助访问本地性。
请参阅Jeff King()的提交0889aae,提交79ed0a5,提交54d2f0d,提交ced9fff(2018年8月14日)和提交0750bb5,提交b1adb38,提交aa2f5ef,提交736eb88,提交8b36155,提交a7ff6f5,提交202e7f1(2018年8月10日)。 
(由Junio C Hamano合并--在commit 0c54cda中,2018年8月20日)peffgitster 
cat-file:支持“unordered”的输出--batch-all-objects如果要访问packfile中每个对象的内容,通常以打包顺序(而不是哈希顺序)进行访问更为有效。这增加了packfile中访问的位置,这又对delta基本缓存更友好,因为packfile将相关的delta彼此相邻放置。相反,由于sha1与内容没有可辨别的关系,因此哈希顺序实际上是随机的。
该补丁引入了一个“
--unordered”选项,cat-file可在引擎盖下按包顺序迭代包。转储所有文件内容时,您可以看到结果:Run Code Online (Sandbox Code Playgroud)$ time ./git cat-file --batch-all-objects --buffer --batch | wc -c 6883195596 real 0m44.491s user 0m42.902s sys 0m5.230s $ time ./git cat-file --unordered \ --batch-all-objects --buffer --batch | wc -c 6883195596 real 0m6.075s user 0m4.774s sys 0m3.548s输出相同,顺序不同,速度更快。即使最终以不同的过程访问对象内容,也可以应用相同的提速,例如:
Run Code Online (Sandbox Code Playgroud)git cat-file --batch-all-objects --buffer --batch-check | grep blob | git cat-file --batch='%(objectname) %(rest)' | wc -c
--unordered在第一个命令中添加“ ”可将运行时间git.git从24秒降至3.5秒。旁注:实际上,现在可以进一步加快处理速度。由于我们是在实际Pack迭代期间输出对象内容的,因此我们知道在哪里可以找到对象,并且可以跳过进行的额外查找
oid_object_info()。该补丁没有进行优化,因为基础API尚未准备好让我们发出这些直接请求。那么,如果
--unordered好得多,为什么不将其设置为默认值呢?两个原因:
我们已经在文档中承诺
--batch-all-objects以哈希顺序输出。由于cat-file存在管道问题,人们可能会依赖该默认值,因此我们无法更改它。
在某些情况下,它实际上要慢一些。我们必须计算包revindex才能按包顺序进行。而且我们的重复数据删除步骤使用的是oidset,而不是sort-and-deedup,这最终会变得更加昂贵。
例如,如果我们只是访问每个对象的类型和大小,例如:
Run Code Online (Sandbox Code Playgroud)git cat-file --batch-all-objects --buffer --batch-check我的5个最佳热缓存时序使用,从900ms变为1100ms
--unordered。尽管在冷缓存或内存压力下,我们可能会做得更好,因为我们在packfile中具有更好的局部性。最后一个问题:为什么是“
--unordered”而不是“--pack-order”?答案还是双重的:
在整个对象集合中,“打包顺序”并不是一个明确定义的东西。我们打松对象,以及为对象在多个包,唯一订购我们看好的是内一个单一的包。其余的显然是随机的。
这里的重点是优化。因此,我们不想承诺任何特定的排序,而只是说我们将选择一种可能对访问对象内容有效的排序。这为将来进行进一步更改打开了大门,而无需添加其他兼容性选项
在Git 2.20(Q4 2018)中,它甚至更快:
见提交8c84ae6,提交8b2f8cb,提交9249ca2,提交22a1646,提交bf73282(2018年10月4日),由勒内Scharfe( )rscharfe。 
(由Junio C gitsterHamano合并--在commit 82d0a8c中,2018年10月19日)  
oidset: 使用khash重新实现
oidset使用khash.h以减少其内存占用并使其更快。主要使用oidset
master和Clang 6.0.1 检查命令是否重复的命令的性能:Run Code Online (Sandbox Code Playgroud)$ cmd="./git-cat-file --batch-all-objects --unordered --buffer --batch-check='%(objectname)'" $ /usr/bin/time $cmd >/dev/null 0.22user 0.03system 0:00.25elapsed 99%CPU (0avgtext+0avgdata 48484maxresident)k 0inputs+0outputs (0major+11204minor)pagefaults 0swaps $ hyperfine "$cmd" Benchmark #1: ./git-cat-file --batch-all-objects --unordered --buffer --batch-check='%(objectname)' Time (mean ± ?): 250.0 ms ± 6.0 ms [User: 225.9 ms, System: 23.6 ms] Range (min … max): 242.0 ms … 261.1 ms
并与此补丁:
Run Code Online (Sandbox Code Playgroud)$ /usr/bin/time $cmd >/dev/null 0.14user 0.00system 0:00.15elapsed 100%CPU (0avgtext+0avgdata 41396maxresident)k 0inputs+0outputs (0major+8318minor)pagefaults 0swaps $ hyperfine "$cmd" Benchmark #1: ./git-cat-file --batch-all-objects --unordered --buffer --batch-check='%(objectname)' Time (mean ± ?): 151.9 ms ± 4.9 ms [User: 130.5 ms, System: 21.2 ms] Range (min … max): 148.2 ms … 170.4 ms
Git 2.21(Q1 2019)通过遵循通常的打包顺序访问对象的模式,进一步优化了代码路径以写出提交图。
见提交d7574c9通过(2019年1月19日)ÆvarArnfjörðBjarmason( )avar。 
(由Junio C gitsterHamano合并--在commit 04d67b6中,2019年2月5日)  
通过使用
FOR_EACH_OBJECT_PACK_ORDER,稍微优化“提交图形写入”步骤for_each_object_in_pack()。
Derrick Stolee 在Windows上进行了自己的测试,结果显示精度提高了2%。
Git 2.23(2019年第三季度)改进了“ git rev-list --objects”功能,该功能通过“ --no-object-names”选项来学习,以压制该对象的路径,该路径用作打包对象的分组提示。
参见Emily Shaffer()提交42357b4(2019年6月19日)。(由Junio C Hamano合并--在commit f4f7e75中,2019年7月9日)nasamuffin
gitster  
rev-list:教--no-object-names如何启用管道
cat-file通过给rev-list选项仅打印未提交对象的OID而没有任何其他信息,可以简化解析。
这是一个短期垫片。稍后,rev-list应该教如何以类似于的格式打印找到的对象类型cat-file。在此提交之前,
rev-list需要先对来自的输出进行按摩,然后再将其通过管道传输到cat文件,如下所示:Run Code Online (Sandbox Code Playgroud)git rev-list --objects HEAD | cut -f 1 -d ' ' | git cat-file --batch-check在处理根树时,这尤其出乎意料,因为OID的末尾存在不可见的空格:
Run Code Online (Sandbox Code Playgroud)git rev-list --objects --filter=tree:1 --max-count=1 HEAD | xargs -I% echo "AA%AA"现在,可以直接通过管道传递它,如添加的测试用例中所示:
Run Code Online (Sandbox Code Playgroud)git rev-list --objects --no-object-names HEAD | git cat-file --batch-check
因此,两者之间的区别在于:
vonc@vonvb:~/gits/src/git$ git rev-list --objects HEAD~1..
9d418600f4d10dcbbfb0b5fdbc71d509e03ba719
590f2375e0f944e3b76a055acd2cb036823d4b44 
55d368920b2bba16689cb6d4aef2a09e8cfac8ef Documentation
9903384d43ab88f5a124bc667f8d6d3a8bce7dff Documentation/RelNotes
a63204ffe8a040479654c3e44db6c170feca2a58 Documentation/RelNotes/2.23.0.txt
并且,使用--no-object-name:
vonc@vonvb:~/gits/src/git$ git rev-list --objects --no-object-names HEAD~1..
9d418600f4d10dcbbfb0b5fdbc71d509e03ba719
590f2375e0f944e3b76a055acd2cb036823d4b44
55d368920b2bba16689cb6d4aef2a09e8cfac8ef
9903384d43ab88f5a124bc667f8d6d3a8bce7dff
a63204ffe8a040479654c3e44db6c170feca2a58
我不知道一个明显更好的方法,而不仅仅是查看所有松散的目标文件和所有包文件的索引.git存储库的格式非常稳定,使用这种方法,您不必依赖于具有完全正确的选项git fsck,这被归类为瓷器.我认为这种方法也更快.以下脚本显示存储库中的所有对象:
#!/bin/sh
set -e
cd "$(git rev-parse --show-cdup)"
# Find all the objects that are in packs:
for p in .git/objects/pack/pack-*.idx
do
    git show-index < $p | cut -f 2 -d ' '
done
# And now find all loose objects:
find .git/objects/ | egrep '[0-9a-f]{38}' | \
  sed -r 's,^.*([0-9a-f][0-9a-f])/([0-9a-f]{38}),\1\2,'
(我的这个脚本的原始版本基于这个有用的脚本来查找包文件中的最大对象,但我转而使用git show-index,如你的问题所示.)
我把这个脚本变成了GitHub的要点.
| 归档时间: | 
 | 
| 查看次数: | 22840 次 | 
| 最近记录: |