Есть ли лучший способ получить необработанный список SHA1 для ВСЕХ объектов в репозитории, чем делать ls .git/objects/??/\*
и cat .git/objects/pack/*.idx | git show-index
?
Ответ 2
Try
git rev-list --objects --all
Изменить Джош сделал хороший момент:
git rev-list --objects -g --no-walk --all
список объектов, доступных из ref-журналов.
Чтобы увидеть все объекты в недостижимых коммитах:
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
Чтобы сортировать результат несколько более полезным способом (по пути для дерева /blobs, сначала фиксируется), используйте дополнительный | sort -k2
, который будет группировать все разные капли (ревизии) для идентичных путей.
Ответ 3
Я не знаю, с какой эта опция существует, но вы можете
git cat-file --batch-check --batch-all-objects
Это дает вам, согласно странице руководства,
все объекты в репозитории и в любом хранилище альтернативных объектов (не только доступные объекты)
(основное внимание).
По умолчанию это дает тип объекта и его размер вместе с каждым хешем, но вы можете легко удалить эту информацию, например. с
git cat-file --batch-check --batch-all-objects | cut -d' ' -f1
или путем предоставления настраиваемого формата --batch-check
.
Ответ 5
Я не знаю, очевидно, лучше, чем просто смотреть на все свободные объектные файлы и индексы всех файлов пакетов. Формат репозитория git очень стабилен, и с помощью этого метода вам не нужно полагаться на правильные опции git fsck
, который классифицируется как фарфор. Я думаю, что этот метод и быстрее. Следующий script показывает все объекты в репозитории:
#!/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,'
(Моя первоначальная версия этого script была основана на этом полезном script, чтобы найти самые большие объекты в ваших файлах пакета, но Я переключился на использование git show-index
, как было предложено в вашем вопросе.)
Я сделал этот script в GitHub gist.
Ответ 6
Команда git cat-file --batch-check --batch-all-objects
, предложенная в ответе git cat-file --batch-check --batch-all-objects
Der Loony, может быть выполнена быстрее с новой опцией Git 2.19 (Q3 2018) --unordered
.
API для итерации по всем изученным объектам, для необязательного перечисления объектов в порядке их появления в пакетных файлах, что помогает обеспечить локальность доступа, если вызывающий объект получает доступ к этим объектам при перечислении объектов.
См. Коммит 0889aae, коммит 79ed0a5, коммит 54d2f0d, коммит ced9fff (14 августа 2018 г.) и коммит 0750bb5, коммит b1adb38, коммит aa2f5ef, коммит 736eb88, коммит 8b36155, коммит a7ff6f5, коммит 202e7f1 (10 авг 2018 peff
) Jeff Jeff, (Объединено Junio C Hamano - gitster
- в коммите 0c54cda, 20 августа 2018 г.)
cat-file
: поддержка " unordered
" вывода для --batch-all-objects
Если вы собираетесь получить доступ к содержимому каждого объекта в файле пакета, как правило, гораздо эффективнее сделать это в порядке упаковки, а не в порядке хэширования. Это увеличивает локальность доступа в файле пакета, что, в свою очередь, более удобно для кеша дельта-базы, поскольку файл пакета помещает связанные дельты рядом друг с другом. В отличие от этого, порядок хеширования является практически случайным, поскольку sha1 не имеет заметной связи с контентом.
Этот патч вводит опцию " --unordered
" в cat-file
который перебирает пачки в порядке упорядочения под капотом. Вы можете увидеть результаты при выгрузке всего содержимого файла:
$ 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
Тот же вывод, другой порядок, намного быстрее. Такое же ускорение применяется, даже если вы в конечном итоге обращаетесь к содержимому объекта в другом процессе, например:
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 с.
Примечание: на самом деле, есть дополнительные ускорения для выполнения всего этого в процессе. Поскольку мы выводим содержимое объекта во время фактической итерации пакета, мы знаем, где найти объект, и можем пропустить дополнительный поиск, выполняемый oid_object_info()
. Этот патч не дотягивает до этой оптимизации, поскольку базовый API не готов к тому, чтобы мы делали подобные запросы напрямую.
Так что, если --unordered
намного лучше, почему бы не сделать его по умолчанию? Две причины:
-
В документации мы обещали, что --batch-all-objects
выводит в порядке хэша. Так как cat-file
является канализацией, люди могут полагаться на это значение по умолчанию, и мы не можем его изменить.
-
Это на самом деле медленнее в некоторых случаях. Мы должны вычислить пакет revindex, чтобы пройти в порядке упаковки. И наш шаг дедупликации использует oidset, а не сортировку и дедупликацию, которая может оказаться более дорогой.
Если мы просто обращаемся к типу и размеру каждого объекта, например:
git cat-file --batch-all-objects --buffer --batch-check
мои лучшие из пяти таймов тайного кэша идут от 900 мс до 1100 мс, используя --unordered
. Хотя в холодном кэше или под нагрузкой памяти возможно, что мы сможем добиться большего успеха, так как у нас будет лучшая локальность в пакете.
И последний вопрос: почему это " --unordered
", а не " --pack-order
"? Ответ опять двоякий:
-
"порядок упаковки" не является четко определенной вещью для всего набора объектов. Мы наносим удары по незакрепленным объектам, а также объектам в нескольких упаковках, и единственный обещаемый нами порядок находится в одной упаковке. Остальное, видимо, случайно.
-
Дело здесь в оптимизации. Таким образом, мы не хотим обещать какой-либо конкретный порядок, а только сказать, что мы выберем порядок, который, вероятно, будет эффективным для доступа к содержимому объекта. Это оставляет дверь открытой для дальнейших изменений в будущем без необходимости добавления другого варианта совместимости.
Это даже быстрее в Git 2.20 (Q4 2018) с:
См. Коммит 8c84ae6, коммит 8b2f8cb, коммит 9249ca2, коммит 22a1646, коммит bf73282 (04 октября 2018 г.) Рене Шарфе (rscharfe
).
(Объединено Юнио К Хамано - gitster
- в коммите 82d0a8c, 19 октября 2018 г.)
oidset
: используйте khash
oidset
с помощью khash.h
, чтобы уменьшить объем используемой памяти и сделать его быстрее.
Выполнение команды, которая в основном проверяет дубликаты объектов, используя oidset, с master
и Clang 6.0.1:
$ 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
И с этим патчем:
$ /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 (19 января 2019 г.) Эвара Арнфьорда Бьярмасона (avar
).
(Объединено Junio C Hamano - gitster
- в коммите 04d67b6, 05 февраля 2019 г.)
Немного оптимизируйте шаг "запись в граф фиксации", используя FOR_EACH_OBJECT_PACK_ORDER
с for_each_object_in_pack()
.
Деррик Столи провел свои собственные тесты на Windows, показав улучшение на 2% с высокой степенью точности.
В Git 2.23 (Q3 2019) улучшен " git rev-list --objects
", который git rev-list --objects
" git rev-list --objects
--no-object-names
", чтобы подавить путь к объекту, который используется в качестве подсказки группировки для pack-объектов.
См. Коммит 42357b4 (19 июня 2019 г.) Эмили Шаффер (nasamuffin
).
(Объединено Junio C Hamano - gitster
- в коммите f4f7e75, 09 июля 2019 г.)
rev-list
: научить --no-object-names
включать трубопровод
Позволяет упростить синтаксический анализ по cat-file
, предоставив rev-list возможность печатать только OID объекта без фиксации без какой-либо дополнительной информации.
Это краткосрочная прокладка; позже, rev-list
должен научиться печатать типы объектов, которые он находит в формате, похожем на cat-file
.
Перед этой фиксацией выходные данные из rev-list
нужно было массировать перед передачей в cat файл, вот так:
git rev-list --objects HEAD | cut -f 1 -d ' ' |
git cat-file --batch-check
Это было особенно неожиданно при работе с корневыми деревьями, поскольку в конце OID существует невидимый пробел:
git rev-list --objects --filter=tree:1 --max-count=1 HEAD |
xargs -I% echo "AA%AA"
Теперь он может быть передан напрямую, как в добавленном тестовом примере:
git rev-list --objects --no-object-names HEAD | git cat-file --batch-check
Так вот в чем разница между:
[email protected]:~/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
:
[email protected]:~/gits/src/git$ git rev-list --objects --no-object-names HEAD~1..
9d418600f4d10dcbbfb0b5fdbc71d509e03ba719
590f2375e0f944e3b76a055acd2cb036823d4b44
55d368920b2bba16689cb6d4aef2a09e8cfac8ef
9903384d43ab88f5a124bc667f8d6d3a8bce7dff
a63204ffe8a040479654c3e44db6c170feca2a58