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 в стиле BSDsed
не поддерживает-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-->
мы обещали в документации, что
--batch-all-objects
выходы в хэш-заказа. Сcat-file
это сантехника, люди могут полагаться на этот дефолт, и мы не можем его изменить.на самом деле медленнее для некоторых случаях. Мы должны вычислить пакет revindex, чтобы ходить в порядке стаи. И наш шаг де-дублирования использует oidset, а не sort-and-dedup, который может оказаться более дорогим.
если мы просто обращаемся к типу и размеру каждого объекта, например, например:
git cat-file --batch-all-objects --buffer --batch-check
мои лучшие из пяти теплых таймингов кэша идут от 900ms до 1100ms, используя
--unordered
. Хотя возможно в холодном тайнике или под давлением памяти, что мы могли бы сделать лучше, так как у нас было бы лучшее место в пределах Pack-файл.и последний вопрос: почему это "
--unordered
", а не "--pack-order
"? Ответ снова двукратный:
"порядок упаковки" не является четко определенной вещью во всем наборе объектов. Мы поражаем свободные объекты, а также объекты в нескольких пакетах, и единственный заказ, который мы обещаем, - это внутри единый пакет. Остальное, по-видимому, случайно.
дело здесь в оптимизации. Так мы не хочу обещать никакого конкретного заказа, но только сказать, что мы выберем заказ, который, вероятно, будет эффективным для доступа к содержимому объекта. Это оставляет дверь открытой для дальнейших изменений в будущем без необходимости добавлять другой вариант совместимости