58

リポジトリ内のすべてのオブジェクトのSHA1の生のリストを取得するためのより良い方法はありますか
ls .git/objects/??/\*

cat .git/objects/pack/*.idx | git show-index

私は知ってgit rev-list --allいますが、それはによって参照されるコミットオブジェクトのみをリストし、などによって作成された参照されていないオブジェクトを含むすべて.git/refsを探しています。git-hash-objectgit-mktree

4

8 に答える 8

44

試す

 git rev-list --objects --all

編集ジョシュは良い点を作りました:

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

ref-logsから到達可能なオブジェクトを一覧表示します。

到達不能なコミット内のすべてのオブジェクトも表示するには:

 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ます)、同じパスのすべての異なるブロブ(リビジョン)をグループ化する追加を使用します。

于 2011-09-08T14:51:11.120 に答える
38

このオプションがいつ存在するかはわかりませんが、できます

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

これにより、マニュアルページによると、

リポジトリ内のすべてのオブジェクトと代替オブジェクトストア(到達可能なオブジェクトだけでなく

(私の強調)。

デフォルトでは、これによりオブジェクトタイプとそのサイズが各ハッシュとともに生成されますが、この情報は簡単に削除できます。

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

または、にカスタム形式を指定し--batch-checkます。

編集:順序を気にしない場合は(Git 2.19以降)フラグを追加して処理--unorderedを高速化できます。詳細については、 VonCの回答を参照してください。

于 2017-12-22T21:08:46.423 に答える
16

これは、 Markwillkillによる回答からの、より正確で、より単純で、より高速なスクリプトの表現です。

  • これは、より複雑なGitリポジトリ設定(たとえば、マルチワークツリーの状況など)でもディレクトリrev-parse --git-pathを見つけるために使用されます。objects

  • find、、、grepの不要な使用をすべて回避しperlますsed

  • 緩いオブジェクトやパックがない場合でも(または、新しいリポジトリでこれを実行する傾向がある場合はどちらも…)、正常に機能する場合。

  • ただし、このミレニアムのBashが必要です(特にextglobビットの場合は2.02以降)。

共有してお楽しみください。

#!/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
于 2016-06-28T18:41:44.813 に答える
16

Erki Der Loony回答で提案されているgit cat-file --batch-check --batch-all-objectsコマンドは、新しいGit 2.19(2018年第3四半期)オプションを使用して高速化できます。--unordered

学習したすべてのオブジェクトを反復処理して、パックファイルに表示される順序でオブジェクトをオプションで一覧表示します。これにより、オブジェクトが列挙されているときに呼び出し元がこれらのオブジェクトにアクセスした場合に、アクセスの場所を特定できます。

コミット0889aae、コミット79ed0a5コミット54d2f0dコミットced9fff(2018年8月14日)、およびコミット0750bb5コミットb1adb38コミットaa2f5efコミット736eb88コミット8b36155コミットa7ff6f5コミット202e7f1 peff 2018年8月10日)を参照してください。 ( Junio C Hamanoによってマージされました---コミット0c54cda、2018年8月20日gitster

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.git24秒から3.5秒に短縮されます。

補足:現在、すべての処理を実行するために、実際にはさらに高速化が可能です。実際のパックの反復中にオブジェクトのコンテンツを出力しているので、オブジェクトの場所がわかっており、によって行われる余分なルックアップをスキップできますoid_object_info()。基盤となるAPIは、この種の直接リクエストを行う準備ができていないため、このパッチはその最適化の手前で停止します。

それで、もし--unorderedもっと良いのなら、それをデフォルトにしてみませんか?2つの理由:

  1. --batch-all-objectsドキュメントでは、ハッシュ順に出力することを約束しました。は配管工事であるためcat-file、人々はそのデフォルトに依存している可能性があり、変更することはできません。

  2. 場合によっては実際には遅くなります。パック順に歩くには、パックのrevindexを計算する必要があります。また、重複排除の手順では、並べ替えと重複排除ではなく、oidsetを使用します。これにより、コストが高くなる可能性があります。

たとえば、各オブジェクトのタイプとサイズにアクセスするだけの場合は、次のようになります。

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

私のベスト5のウォームキャッシュのタイミングは、を使用して900ミリ秒から1100ミリ秒になり--unorderedます。コールドキャッシュまたはメモリ不足の場合は、パックファイル内のローカリティが向上するため、より適切に実行できる可能性があります。

そして最後の質問です。なぜそれは「--unordered」ではなく「--pack-order」なのですか?答えは再び2つあります。

  1. 「パックの順序」は、オブジェクトのセット全体で明確に定義されたものではありません。私たちはルーズなオブジェクトと複数のパックのオブジェクトをヒットしており、私たちが約束している唯一の注文は単一のパック内です。残りは明らかにランダムです。

  2. ここでのポイントは最適化です。したがって、特定の順序を約束する必要はありませんが、オブジェクトのコンテンツにアクセスするのに効率的である可能性が高い順序を選択すると言うだけです。これにより、別の互換性オプションを追加することなく、将来のさらなる変更への扉が開かれたままになります。


Git 2.20(2018年第4四半期)では、次のようにさらに高速になります。

RenéScharfe ()によるcommit 8c84ae6、 commit 8b2f8cbcommit 9249ca2commit 22a1646commit bf73282 rscharfe 2018年10月4日)を参照してください。( Junio C Hamano
によってマージされました---コミット82d0a8c、2018年10月19日gitster

oidset: 使用するkhash

メモリフットプリントを削減し、高速化するために、oidsetを使用して再実装します。khash.h

masterClang 6.0.1で、主にoidsetを使用して重複オブジェクトをチェックするコマンドのパフォーマンス:

$ 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(2019年第1四半期)は、パック内の順序でオブジェクトにアクセスする通常のパターンに従うことにより、commit-graphを書き出すためのコードパスをさらに最適化します。

ÆvarArnfjörðBjarmason ( )によるcommit d7574c9(2019年1月19日)を参照してください。( Junio C Hamanoによってマージされました---コミット04d67b6、2019年2月5日avar
gitster

を使用して、「commit-graphwrite」ステップをわずかに最適化 FOR_EACH_OBJECT_PACK_ORDERfor_each_object_in_pack()ます。
Derrick Stoleeは、Windowsで独自のテストを行い、高い精度で2%の改善を示しました。


Git 2.23(2019年第3四半期)は、パックオブジェクトのグループ化ヒントとして使用されるオブジェクトへのパスをスケルチするためのgit rev-list --objects「」オプションで学習した「」を改善します。--no-object-names

Emily Shaffer()によるcommit 42357b4(2019年6月19日)を参照してください。( Junio C Hamanoによってマージされました---コミットf4f7e75、2019年7月9日nasamuffin
gitster

rev-list--no-object-names:配管を有効にすることを教える

cat-file追加情報なしで非コミットオブジェクトのOIDのみを出力するオプションをrev-listに与えることにより、より簡単な解析を可能にします。
これは短期間のシムです。後で、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

Git 2.31(Q1 2021)では、コア内のrevindexへの抽象アクセスにより、パックファイルに格納されているオブジェクトをパックに表示される順序で列挙できるようになり、ディスク上で事前計算されたrevindexを導入する準備が整います。これにより、これらの操作が高速化されます。

commit e5dcd78、commit d5bc7c6commit 8389855commit 1c3855fcommit 2891b43、commit b130aef commit 0a7e364 commit fc150cacommit 3a3f54dcommit 45bef5ccommit 78232bf 、commit 011f3fd 、commit a78 6a5c10cコミット66cbd3eコミット952fc68コミットf33fb6e(2021年1月13日)テイラーブラウ(ttaylorrJeff King()によるcommit 779412b(2021年1月14日)
を参照してください。( Junio C Hamanoによってマージされました---コミットbcaaf97、2021年1月25日peff
gitster

pack-revindex:新しいAPIを導入する

サインオフ-作成者:Taylor Blau

.idx次のいくつかのパッチでは、メモリに逆インデックスをロードする(コア内のコンテンツの逆をマッピングする)か、まだ導入されていないディスク上のフォーマットから直接ロードする準備をします。
その準備として、呼び出し元が構造内のrevindexポインターに明示的にインデックスを付けることを回避するAPIを導入しますpacked_git

リバースインデックスを操作する方法は4つあります。したがって、既存のAPIが削除さ
れるまでに、4つの関数が''からエクスポートされます。 発信者は次のことを行うことができます。pack-revindex.h

  1. パックのリバースインデックスをロードします。
    これには、インデックスを開き、配列を生成してから並べ替えることが含まれます。
    インデックスを開くことが失敗する可能性があるため、この関数(' load_pack_revindex()')はintを返します。
    したがって、それは単一の引数のみを取ります:' struct packed_git'''呼び出し元はの逆インデックスを構築したいと考えています。
    この関数は、現在のAPIと新しいAPIの両方に適しています。
    呼び出し元は引き続きリバースインデックスを明示的に開く必要がありますが、この関数は最終的に、ディスク上のフォーマット(存在する場合)からリバースインデックスを検出してロードする方法を学習します。
    それ以外の場合は、メモリ内に最初から生成することにフォールバックします。

  2. パック位置をオフセットに変換します。
    この操作は現在、と呼ばれてpack_pos_to_offset()います。
    パックと位置を取り、対応するを返しますoff_t
    呼び出し元は障害を処理して続行するのに適していないため、エラーが発生するとBUG()が呼び出されます。

  3. パック位置をインデックス位置に変換します。
    同上; これはパックと位置を取り、を返しますuint32_t
    この操作はとして知られていpack_pos_to_index()ます。
    エラー状態についての同じ考え方がここでも当てはまります。

  4. 特定のオフセットのパック位置を見つけます。
    この操作は現在、として知られていoffset_to_pack_pos()ます。オブジェクトがそのオフセットに存在する場合は
    、パック、オフセット、および位置が書き込まれる場所へのポインターが必要です。 それ以外の場合は、失敗を示すために-1が返されます。uint32_t

以前は直接アクセス'->offset'していた一部の発信者とは異なり、この呼び出しに関するエラーチェックはやや堅牢です。 呼び出し元は常に2つのオブジェクトの境界を指すオフセットを渡す必要があるため、これは重要です。 APIは、直接アクセスとは異なり、それを強制します。'->nr'

これは、戻り値をチェックしないがチェックできる呼び出し元が、signedfromを'revindex'配列へのインデックスとして扱う後続のパッチで重要になり-1ますfind_revindex_position()

2つの設計いぼが新しいAPIに引き継がれています。

  • 範囲外のオブジェクトのインデックス位置を要求すると(そのようなオブジェクトが存在しないため)BUG()になりますが、パックの最後に存在しないオブジェクトのオフセットを要求すると、の合計サイズが返されます。パック。
    これにより、(ディスク上のサイズを計算するために)隣接する2つのオブジェクトのオフセットの差を常に取得したいが、パックの最後の境界について心配したくない呼び出し元にとって便利です。
  • offset_to_pack_pos()逆インデックスを遅延ロードしますが、ロードpack_pos_to_index()しません(前者の呼び出し元はエラーの処理に適していますが、後者の呼び出し元はそうではありません)。

Git 2.32(2021年第2四半期)では、" git (branch|tag) --format=..."がマイクロ最適化されています。

ZheNing Hu()によるcommit 844c3f0 ( 2021年4月20日)およびcommit 22f69a8(2021年4月19日)を参照してください。( Junio C Hamanoによってマージされました---コミットc108c8c、2021年5月7日adlternative
gitster

ref-filter:出力バッファを再利用する

支援者:Junio C Hamano
支援者:Jeff King
支援者
:RenéScharfe署名者:ZheNing Hu

manを使用すると、すべてのrefが独自の出力strbufとエラーstrbufを割り当てます。 ただし、各ステップrefの出力に最終的なstrbufを再利用できます。ゼロ以外の値を返し、エラーバッファの内容を出力すると 、gitが終了するという事実にもかかわらず、エラーバッファも再利用されます。git for-each-ref

format_ref_array_item()

パフォーマンスgit for-each-refテストツールを使用したGitリポジトリ自体のパフォーマンスhyperfineは、23.7ミリ秒±0.9ミリ秒から22.2ミリ秒±1.0ミリ秒に変更されます。
最適化は比較的マイナーです。

同時に、この最適化をmanmanに適用します。git tag -lgit branch -l

このアプローチは、組み込みのcat-fileを高速化するために79ed0a5( " cat-file:すべての出力に単一のstrbufを使用する"、2018-08-14、Git v2.19.0-rc0 --merge)で使用されるアプローチに似ています。

于 2018-08-21T21:01:06.197 に答える
10

編集: アリストテレスはさらに良い答えを投稿しました。これは正解としてマークする必要があります。

編集:grep -vスクリプトに構文エラーが含まれており、行末に円記号がありません

いくつかの変更を加えた後、マークの答えは私のために働いた:

  • ベアリポジトリをサポートする--git-dir代わりに使用--show-cdup
  • パックがない場合のエラーの回避
  • perlOS XMountainLionの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}):\1\2:' \
;
于 2012-08-14T16:39:46.830 に答える
7

すべてのルーズオブジェクトファイルとすべてのパックファイルのインデックスを確認するよりも明らかに良い方法はわかりません。git fsckgitリポジトリの形式は非常に安定しており、この方法を使用すると、磁器として分類されるに正確に適切なオプションがあることに依存する必要はありません。この方法も速いと思います。次のスクリプトは、リポジトリ内のすべてのオブジェクトを示しています。

#!/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たが、質問で提案されているように、を使用するように切り替えました。)

このスクリプトをGitHubの要点にしました。

于 2011-09-12T16:00:10.977 に答える
3

もう1つの便利なオプションは、git verify-pack -v <packfile>

verify-pack -vデータベース内のすべてのオブジェクトとそのオブジェクトタイプを一覧表示します。

于 2013-09-13T18:37:03.673 に答える
1

Erki der Loonyseheソリューションを組み合わせると、ほぼすべてのblobオブジェクトファイル名を取得できます(gitで除外されたファイルを除く)。

git cat-file --batch-check --batch-all-objects | grep blob | cut -d" " -f1 | xargs -n1 git rev-list --objects -g --no-walk --all > .recovered/allblobobject.txt
cat .recovered/allblobobject.txt | sort | uniq > .recovered/allblobuniqobject.txt

このblobからファイル名へのマップは、次の方法で取得された消失したファイルを回復するために使用できます。

git fsck --full --no-reflogs --unreachable --lost-found | grep blob | cut -d" " -f3 > .recovered/bloblist.txt
for /F "tokens=*" %A in (.recovered/bloblist.txt) do (git cat-file -p %A > .recovered/%A)
于 2021-01-24T04:43:06.560 に答える