web-dev-qa-db-ja.com

Git-データベース内のすべてのオブジェクトをリストする方法

リポジトリ内のすべてのオブジェクトの未加工のSHA1リストを取得するより良い方法はありますかls .git/objects/??/\*およびcat .git/objects/pack/*.idx | git show-index

git rev-list --allしかし、それは.git/refsによって参照されるコミットオブジェクトのみを一覧表示し、私はeverythingを探しています。git-hash-object、git-mktreeなどによって作成される参照されていないオブジェクトを含みます。

48
kbro

編集:アリストテレス 掲載 さらに良い回答 、これは正しいとマークされるべきです。

編集:スクリプトに構文エラーがあり、grep -v行の最後にバックスラッシュがありません

いくつかの修正を行った後、Markの答えはうまくいきました。

  • --git-dirの代わりに--show-cdupを使用して、裸のリポジトリをサポートしました
  • パックがない場合のエラーを回避
  • OS X Mountain LionのBSDスタイルPerl-rをサポートしていないため、sedを使用しました
#!/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:' \
;
9
willkil

試して

 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)

すべてをまとめて、reallyにすべてのオブジェクトを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を使用します。これは、同一パスのすべての異なるブロブ(リビジョン)をグループ化します。

35
sehe

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

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

これにより、manページによると、

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

(強調鉱山)。

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

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

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

22
Erki der Loony

これは、答え マークによる および ウィルキルによる からのスクリプトのより正確で、より単純で、より速い表現です。

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

  • findgrepPerlsedの不要な使用をすべて回避します。

  • ゆるいオブジェクトやパックがなくても(または、新しいリポジトリでこれを実行する場合はどちらでも)正常に動作します。

  • ただし、このミレニアムの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
8

すべてのルーズオブジェクトファイルとすべてのパックファイルのインデックスを確認するよりも、明らかに優れた方法を知りません。 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、あなたの質問で提案されたとおり。)

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

6
Mark Longair

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

学習したすべてのオブジェクトを反復処理するAPIオプションでオブジェクトをpackfilesに表示される順序でリストします。これにより、呼び出し元がこれらのオブジェクトにアクセスする場合、オブジェクトが列挙されるため。

commit 0889aaecommit 79ed0a5commit 54d2f0d を参照/、 commit ced9fff (2018年8月14日)、および commit 0750bb5commit b1adb38commit aa2f5efcommit 736eb88commit 8b36155commit a7ff6f5commit 202e7f1 (2018年8月10日) ジェフ・キング(peff 。 Junio C Hamano-gitster- in commit 0c54cda 、8月20日で合併2018)

cat-file--batch-all-objectsの「unordered」出力をサポート

パックファイル内のすべてのオブジェクトのコンテンツにアクセスする場合、一般的にハッシュ順ではなくパック順でアクセスする方がはるかに効率的です。これにより、パックファイル内のアクセスの局所性が向上します。これは、パックファイルが関連するデルタを隣り合わせに配置するため、デルタベースキャッシュにとってより使いやすくなります。対照的に、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の方がはるかに優れている場合、デフォルトにしないのはなぜですか? 2つの理由:

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

  2. 実際には slower です。パック順で歩くには、パックのrevindexを計算する必要があります。そして、重複排除の手順では、ソートと重複ではなく、oidsetを使用します。

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

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

--unorderedを使用すると、ベスト5のウォームキャッシュタイミングは900ミリ秒から1100ミリ秒になります。コールドキャッシュまたはメモリのプレッシャーの中で、パックファイル内のローカリティが向上するため、より良い結果を得ることができます。

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

  1. 「パック順序」は、オブジェクトのセット全体で明確に定義されたものではありません。複数のパックのオブジェクトと同様に、ゆるいオブジェクトをヒットしています。そして、約束している唯一の順序は within 単一のパックです。残りは明らかにランダムです。

  2. ここでのポイントは最適化です。そのため、特定の順序を約束するのではなく、オブジェクトのコンテンツにアクセスするのに効率的な順序を選択するというだけです。これにより、別の互換性オプションを追加することなく、将来のさらなる変更に対応できます。


Git 2.20(2018年第4四半期)ではさらに高速です:

commit 8c84ae6commit 8b2f8cbcommit 9249ca2 を参照/、 commit 22a1646commit bf73282 (2018年10月4日)by ルネ・シャーフ(rscharfe
Junio C Hamano-gitster- in commit 82d0a8c 、10月19日で合併2018)

oidsetkhashを使用

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

masterおよびClang 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 d7574c9 (2019年1月19日)by ÆvarArnfjörðBjarmason(avar を参照してください。
ジュニオC浜野-gitster- in commit 04d67b6 、2月5日2019)

for_each_object_in_pack()とともにFOR_EACH_OBJECT_PACK_ORDERを使用して、「commit-graph write」ステップを少し最適化します。
Derrick Stoleeは、Windowsで 彼自身のテストを行いました 高い精度で2%の改善を示しました。


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

commit 42357b4 (2019年6月19日)by Emily Shaffer(nasamuffin を参照してください。
Junio C Hamano-gitster- in commit f4f7e75 、09 Jul 2019)

rev-list:パイピングを有効にするために--no-object-namesを教える

Rev-listに、追加情報なしで非コミットオブジェクトのOIDのみ)を出力するオプションを与えることにより、cat-fileによる簡単な解析を許可します。
これは短期的なシムです。後で、rev-listは、検出したオブジェクトのタイプをcat-fileのような形式で印刷する方法を教える必要があります。

このコミットの前に、次のように、rev-listからの出力をcatファイルにパイプする前にマッサージする必要がありました。

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
5
VonC

別の便利なオプションは、git verify-pack -v <packfile>

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

2
nimrodm