Git - как перечислить все объекты в базе данных

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

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

7 ответов


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

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

  • используется --git-dir вместо --show-cdup для поддержки голые РЕПО
  • избежать ошибки, когда нет пакетов
  • используется perl потому что OS X Mountain Lion в стиле BSD 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})::' \
;

попробовать

 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, commits first) используйте дополнительный | sort -k2 который сгруппирует все разные капли (ревизии) для одинаковых путей.


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

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

Это дает вам, согласно man page,

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

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

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

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

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


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

(моя первоначальная версия этого сценария была основана на этот полезный скрипт для поиска самых больших объектов в файлах вашего пакета, но я переключился с использованием git show-index, как предложено в вашем вопросе.)

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


это более правильное, простое и быстрое исполнение скрипта из ответов Марк и по willkill.

  • он использует rev-parse --git-path найти objects каталог даже в более сложной настройке репозитория Git (например, в ситуации с несколькими рабочими деревьями или еще что-то).

  • это позволяет избежать ненужного использования find, grep, perl, sed.

  • если работает корректно даже если у вас нет свободных объектов или пакетов (или ни одного... если вы склонны запускать это в новом репозитории).

  • однако для этого требуется Bash из этого тысячелетия (2.02 или новее, в частности, для


еще один полезный вариант-использовать git verify-pack -v <packfile>

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


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

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

посмотреть совершить 0889aae, совершить 79ed0a5, совершить 54d2f0d, совершить ced9fff (14 Авг 2018), и совершить 0750bb5, совершить b1adb38, совершить aa2f5ef, совершить 736eb88, совершить 8b36155, совершить a7ff6f5, совершить 202e7f1 (10 Авг 2018) by Джефф Кинг (peff). (слитый Junio C Hamano -- gitster -- на совершить 0c54cda, 20 авг 2018)

cat-file: поддержка "unordered" выход для --batch-all-objects

если вы собираетесь получить доступ к содержимому каждого объекта в packfile,обычно гораздо эффективнее делать это в порядке упаковки, а не в порядке хэша. Это увеличивает локальность доступа в пределах packfile, который, в свою очередь, более дружелюбен к базовому кэшу delta, так как packfile помещает связанные дельты рядом друг с другом. Напротив, хеш-порядок является фактически случайным, так как sha1 не имеет различимого отношение к содержанию.

этот патч вводит "--unordered опции"cat-file который повторяет пакеты в pack-order под капотом. Вы можете увидеть результаты при сбросе всего содержимого файла:

$ 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 намного лучше, почему бы не сделать его по умолчанию? Две причины:--30-->

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

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

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

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

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

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

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

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