Git - как вывести ВСЕ объекты в базу данных - PullRequest
48 голосов
/ 08 сентября 2011

Есть ли лучший способ получить необработанный список SHA1 для ВСЕХ объектов в репозитории, чем делать ls .git/objects/??/\* и cat .git/objects/pack/*.idx | git show-index?

Я знаю о git rev-list --all, но в нем перечислены только те коммиты, которыессылаются на .git / refs, и я ищу все , включая объекты без ссылок, созданные git-hash-object, git-mktree и т. д.

Ответы [ 7 ]

35 голосов
/ 08 сентября 2011

Попробуйте

 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)

Собрав все вместе, действительно получим все объекты в выходном формате 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

Чтобы отсортировать вывод немного более полезным способом (по пути для дерева / больших двоичных объектов, сначала фиксирует), используйте дополнительный | sort -k2, который сгруппирует все различные большие двоичные объекты (ревизии) для одинаковых путей.

20 голосов
/ 23 декабря 2017

С тех пор, когда эта опция существует, я не знаю, но вы можете

git cat-file --batch-check --batch-all-objects

Это дает вам, согласно man-странице,

все объекты в хранилище и любые альтернативные хранилища объектов ( не только достижимые объекты )

(выделено мое).

По умолчанию это дает тип объекта и его размер вместе с каждым хешем, но вы можете легко удалить эту информацию, например, с

git cat-file --batch-check --batch-all-objects | cut -d' ' -f1

или путем задания пользовательского формата --batch-check.

9 голосов
/ 14 августа 2012

Редактировать: Аристотель отправил еще лучший ответ , который следует пометить как правильный.

Редактировать: сценарий содержал синтаксическую ошибку, пропуская обратную косую черту в конце строки grep -v

Ответ Марка сработал для меня после нескольких модификаций:

  • Использовано --git-dir--show-cdup для поддержки голых репозиториев
  • Предотвращение ошибок при отсутствии пакетов
  • Используется perl, поскольку BSD-стиль OS X Mountain Lion sed не поддерживает -r

#!/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:' \
;
8 голосов
/ 28 июня 2016

Это более правильное, более простое и быстрое исполнение сценария из ответов Марка и Вилкилла .

  • Он использует 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
6 голосов
/ 12 сентября 2011

Я не знаю, очевидно, лучшего способа, чем просто смотреть на все свободные объектные файлы и индексы всех файлов пакета.Формат репозитория 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, как предложено в вашем вопросе.)

Я превратил этот скрипт в GistHub gist .

5 голосов
/ 22 августа 2018

Команда git cat-file --batch-check --batch-all-objects, предложенная в Erki Der Loony ответ , может быть сделана быстрее с новой опцией Git 2.19 (Q3 2018)--unordered.

API для итерации по всем изученным объектам для опционально перечисления объектов в порядке их появления в пакетных файлах , что помогает в локальности доступа, если вызывающая сторонаобращается к этим объектам, пока они перечисляются.

См. commit 0889aae , commit 79ed0a5 , commit 54d2f0d , commit ced9fff (14 августа 2018 г.) и коммит 0750bb5 , коммит b1adb38 , коммит aa2f5ef , коммит 736eb88 , коммит 8b36155 , коммит a7ff6f5 , коммит 202e7f1 (10 августа 2018) Джефф Кинг (peff) . (Объединено с 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 намного лучше, почему бы не сделать его по умолчанию?Две причины:

  1. Мы обещали в документации, что --batch-all-objects выводит в порядке хэширования.Так как cat-file является сантехникой, люди могут полагаться на это значение по умолчанию, и мы не можем его изменить.

  2. Это на самом деле медленнее в некоторых случаях.Мы должны вычислить пакет revindex, чтобы пройти в порядке упаковки.И наш шаг дедупликации использует oidset, а не сортировку и дедупликацию, которая может оказаться более дорогой.

Если мы просто получим доступ к типу и размеру каждого объекта, например, например:

git cat-file --batch-all-objects --buffer --batch-check

, то пойдут мои лучшие таймы тайникаот 900 мс до 1100 мс, используя --unordered.Хотя возможно в холодном кэше или под давлением памяти мы могли бы добиться большего успеха, так как у нас была бы лучшая локальность в файле пакета.

И последний вопрос: почему это "--unordered", а не"--pack-order"?Ответ снова двоякий:

  1. «порядок упаковки» не является четко определенной вещью для всего набора объектов.Мы наносим удары по незакрепленным объектам, а также объектам в нескольких упаковках, и единственный обещаемый нами порядок - это в пределах одного пакета.Остальное, по-видимому, случайно.

  2. Дело здесь в оптимизации.Таким образом, мы не хотим обещать какой-либо конкретный порядок, а только сказать, что мы выберем порядок, который, вероятно, будет эффективным для доступа к содержимому объекта.Это оставляет дверь открытой для дальнейших изменений в будущем без необходимости добавления другого параметра совместимости


Это еще быстрее в Git 2.20 (Q4 2018) с:

См. commit 8c84ae6 , commit 8b2f8cb , commit 9249ca2 , коммит 22a1646 , коммит bf73282 (04 октября 2018 г.) Рене Шарфе (rscharfe) .
(объединено JunioC Hamano - 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) оптимизируетдалее код пути для записи commit-графа, следуя обычному шаблону посещения объектов в порядке в упаковке.

См. commit d7574c9 (19 января 2019) от Ævar ArnfjörðБьярмасон (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», которое выучено с опцией «--no-object-names», чтобы подавить путь к объекту, который используется в качестве подсказки группировкидля упаковочных объектов.

См. коммит 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-file, вот так:

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

Так что разница между:

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
2 голосов
/ 13 сентября 2013

Еще одна полезная опция - использовать git verify-pack -v <packfile>

verify-pack -v, чтобы перечислить все объекты в базе данных вместе с их типом объекта.

...