Git – como listar todos os objects no database

Existe uma maneira melhor de obter uma lista bruta de SHA1s para todos os objects em um repository do que fazer ls .git/objects/??/\* e cat .git/objects/pack/*.idx | git show-index cat .git/objects/pack/*.idx | git show-index ?

Eu sei sobre git rev-list --all mas que apenas lista commit objects que são referenciados por .git / refs, e eu estou procurando por tudo, incluindo os objects não referenciados que são criados por git-hash-object, git-mktree etc.

    Edit: Aristóteles postou uma resposta ainda melhor , que deve ser marcada como correta.

    A resposta de Mark funcionou para mim depois de algumas modificações:

    • Usado --git-dir vez de --show-cdup para suportar repos nus
    • Erro evitado quando não há pacotes
    • perl usado porque sed estilo BSD do OS X Mountain Lion não suporta -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:' \ ; 

    Experimentar

      git rev-list --objects --all 

    Edit Josh fez um bom ponto:

      git rev-list --objects -g --no-walk --all 

    lista de objects alcançáveis ​​a partir dos logs de ref.

    Para ver todos os objects em commits inacessíveis também:

      git rev-list --objects --no-walk \ $(git fsck --unreachable | grep '^unreachable commit' | cut -d' ' -f3) 

    Juntando tudo, para realmente obter todos os objects no formato de saída de objects rev-list --objects , você precisa de algo como

     { 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 

    Para classificar a saída de maneira um pouco mais útil (pelo caminho para tree / blobs, commits primeiro) use um adicional | sort -k2 | sort -k2 que | sort -k2 todos os diferentes blobs (revisões) para caminhos idênticos.

    Eu não sei desde quando esta opção existe, mas você pode

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

    Isso te dá, de acordo com a página man,

    todos os objects no repository e quaisquer armazenamentos de objects alternativos ( não apenas objects alcançáveis )

    (ênfase minha).

    Por padrão, isso gera o tipo de object e seu tamanho junto com cada hash, mas você pode facilmente remover essas informações, por exemplo, com

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

    ou dando um formato customizado para --batch-check .

    Eu não sei de uma maneira obviamente melhor do que apenas olhar para todos os arquivos de objects soltos e os índices de todos os arquivos de pacotes. O formato do repository git é muito estável, e com este método você não tem que confiar em ter exatamente as opções corretas para o git fsck , que é classificado como porcelana. Eu acho que esse método é mais rápido também. O script a seguir mostra todos os objects em um repository:

     #!/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,' 

    (Minha versão original deste script foi baseada neste script útil para encontrar os maiores objects em seus arquivos de pacote , mas eu mudei para usar o git show-index , como sugerido na sua pergunta.)

    Eu fiz este script em uma essência do GitHub .

    Esta é uma versão mais correta, mais simples e mais rápida do script das respostas de Mark e por willkill .

    • Ele usa rev-parse --git-path para encontrar o diretório de objects , mesmo em uma configuração de repository Git mais complexa (por exemplo, em uma situação multi-worktree ou qualquer outra coisa).

    • Evita todo o uso desnecessário de find , grep , perl , sed .

    • Se funciona bem, mesmo se você não tiver objects soltos ou nenhum pacote (ou nenhum dos dois … se você estiver inclinado a executá-lo em um novo repository).

    • No entanto, exige um Bash deste milênio 😊 (2.02 ou mais recente, especificamente, para o bit extglob ).

    Compartilhe e aproveite.

     #!/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 

    Outra opção útil é usar o git verify-pack -v

    verify-pack -v lista todos os objects no database junto com seu tipo de object.

    O comando git cat-file --batch-check --batch-all-objects , sugerido na resposta de Erki Der Loony , pode ser feito mais rapidamente com a nova opção Git 2.19 (Q3 2018) --unordered .

    A API para iterar todos os objects aprendidos para, opcionalmente, listar objects na ordem em que aparecem nos arquivos de pacote , o que ajuda a localidade de access se o chamador acessar esses objects enquanto os objects são enumerados.

    Veja cometer 0889aae , cometer 79ed0a5 , cometer 54d2f0d , confirmar ced9fff (14 Ago 2018), e cometer 0750bb5 , cometer b1adb38 , cometer aa2f5ef , cometer 736eb88 , cometer 8b36155 , cometer a7ff6f5 , cometer 202e7f1 (10 Ago 2018) por Jeff King ( peff ) . (Mesclado por Junio ​​C Hamano – gitster – em commit 0c54cda , 20 de agosto de 2018)

    cat-file : suporta saída ” unordered ” para --batch-all-objects

    Se você for acessar o conteúdo de todos os objects em um arquivo de pacote, geralmente é muito mais eficiente fazer isso na ordem do pacote do que na ordem de hash . Isso aumenta a localidade de access dentro do arquivo de pacotes, que por sua vez é mais amigável ao cache de base delta, uma vez que o arquivo de pacotes coloca deltas relacionados próximos uns dos outros. Por outro lado, a ordem hash é efetivamente aleatória, uma vez que a sha1 não tem relação discernível com o conteúdo.

    Este patch introduz uma opção ” --unordered ” para cat-file que itera em pacotes na ordem de pacotes sob o capô. Você pode ver os resultados ao descartar todo o conteúdo do arquivo:

     $ 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 

    Mesma saída, ordem diferente, muito mais rápido. A mesma aceleração se aplica mesmo que você acabe acessando o conteúdo do object em um processo diferente, como:

     git cat-file --batch-all-objects --buffer --batch-check | grep blob | git cat-file --batch='%(objectname) %(rest)' | wc -c 

    Adicionar ” --unordered ” ao primeiro comando descarta o tempo de execução em git.git de 24s para 3.5s.

    Nota: há mais acelerações disponíveis para fazer tudo em processo agora. Como estamos produzindo o conteúdo do object durante a iteração real do pacote, sabemos onde encontrar o object e podemos pular a pesquisa extra feita pelo oid_object_info() . Esse patch é interrompido por essa otimização, pois a API subjacente não está pronta para fazer esse tipo de solicitação direta.

    Então, se – --unordered é muito melhor, por que não torná-lo o padrão? Duas razões:

    1. Nós prometemos na documentação que --batch-all-objects saídas de --batch-all-objects em ordem de hash. Como o cat-file é o encanamento, as pessoas podem confiar nesse padrão, e não podemos alterá-lo.

    2. Na verdade, é mais lento em alguns casos. Nós temos que calcular o pacote de indexação para andar na ordem do pacote. E nossa etapa de desduplicação usa um oidset, em vez de uma sorting e dedução, que pode acabar sendo mais cara.

    Se estamos apenas acessando o tipo e tamanho de cada object, por exemplo, como:

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

    meus tempos de cache mais quentes de cinco passam de 900ms a 1100ms usando --unordered . Embora seja possível em um cache frio ou sob pressão de memory que poderíamos fazer melhor, uma vez que teríamos uma melhor localização dentro do pacote.

    E uma última pergunta: por que é ” --unordered ” e não ” --pack-order “? A resposta é novamente dupla:

    1. “ordem de embalagem” não é uma coisa bem definida em todo o conjunto de objects. Estamos atingindo objects soltos, bem como objects em vários pacotes, e a única ordem que estamos prometendo está em um único pacote. O resto é aparentemente random.

    2. O ponto aqui é otimização. Portanto, não queremos prometer nenhuma ordem específica, mas apenas dizer que escolheremos uma ordem que provavelmente será eficiente para acessar o conteúdo do object. Isso deixa a porta aberta para mais mudanças no futuro sem ter que adicionar outra opção de compatibilidade