質問

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

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

役に立ちましたか?

解決

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

編集: スクリプトには構文エラーが含まれており、最後にバックスラッシュがありません grep -v ライン

マークの答えは、いくつかの修正の後、私のために働きました:

  • 使用済み --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}):\1\2:' \
;

他のヒント

試す

 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 これは、同一のパスに対してすべての異なる塊(改訂)をグループ化します。

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

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

Manページによると、これはあなたに与えます、

すべてのオブジェクト リポジトリおよび代替オブジェクトストア(到達可能なオブジェクトだけではありません)

(マイニングの強調)。

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

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

または、カスタム形式を提供します --batch-check.

これは、回答からスクリプトのより正確で、よりシンプルで、より速い演出です マークによってWillkillによって.

  • それは使用しています rev-parse --git-path を見つける objects より複雑なgitリポジトリのセットアップでもディレクトリ(マルチワークツリーの状況など)。

  • それはすべての不必要な使用を回避します find, grep, perl, sed.

  • ゆるいオブジェクトやパックがない場合でも優雅に機能する場合(または、これを新鮮なリポジトリで実行する傾向がある場合)。

  • ただし、このミレニアムからのバッシュが必要です(具体的には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

すべてのルーズオブジェクトファイルとすべてのパックファイルのインデックスを見るよりも、明らかに良い方法を知りません。 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.

git cat-file --batch-check --batch-all-objects コマンド、提案された erki derloony's 答え, 、作ることができます もっと早く 新しいgit2.19(2018年第3四半期)オプション --unordered.

APIは、学んだすべてのオブジェクトを反復します オプションでオブジェクトを順にリストします。パックファイルに表示されます, 、オブジェクトが列挙されているときに、発信者がこれらのオブジェクトにアクセスする場合、アクセスの局所性を支援します。

見る コミット0889aae, 79ED0A5をコミットします, 54D2F0Dをコミットします, CED9FFFをコミットします (2018年8月14日)、 コミット0750bb5, B1ADB38をコミットします, AA2F5EFをコミットします, コミット736EB88, コミット8B36155, a7ff6f5をコミットします, コミット202E7F1 (2018年8月10日) ジェフ・キング(peff). (融合 Junio C Hamano- gitster --0C54CDAをコミットします, 、2018年8月20日)

cat-file: : サポート "unordered「出力 --batch-all-objects

パックファイル内のすべてのオブジェクトのコンテンツにアクセスする場合は、 通常、ハッシュオーダーではなく、パック順序でそうする方がはるかに効率的です. 。これにより、PackFile内のアクセスの局所性が向上し、PackFileが関連するデルタを互いに隣接させるため、Delta Base Cacheに友好的です。対照的に、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. それは実際です もっとゆっくり 場合によっては。 Pack Revindexを計算して、パックの順序で歩く必要があります。また、重複式のステップでは、ソートアンドディッドアップではなく、OIDSetを使用します。これは、より高価になる可能性があります。

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

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

私のベスト5の温かいキャッシュタイミングは、900mmから1100msを使用します --unordered. 。 Cold-CacheまたはMemory Pressureでは、PackFile内のより良い局所性があるので、より良いことができる可能性があります。

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

  1. 「パックオーダー」は、オブジェクト全体にわたって明確に定義されたものではありません。私たちは複数のパックのオブジェクトと同様にゆるいオブジェクトを押していますが、私たちが約束している唯一の注文は 内部 シングルパック。残りは明らかにランダムです。

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


GIT 2.20(2018年第4四半期)でさらに高速です。

見る コミット8C84AE6, コミット8B2F8CB, コミット9249CA2, コミット22A1646, BF73282をコミットします (2018年10月4日) ルネ・シャーフ(rscharfe).
(融合 Junio C Hamano- gitster --コミット82D0A8C, 、2018年10月19日)

oidset: : 使用する khash

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

主にoidsetを使用して重複したオブジェクトをチェックするコマンドのパフォーマンス master およびClang 6.0.1:

$ 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四半期)は、コードパスをさらに最適化して、インパック順にオブジェクトを訪問する通常のパターンに従うことにより、コミットグラフを書きます。

見る D7574C9をコミットします (2019年1月19日) ævararnfjörðbjarmason(avar).
(融合 Junio C Hamano- gitster --コミット04d67b6, 、2019年2月5日)

使用して「コミットグラフ書き込み」ステップをわずかに最適化します FOR_EACH_OBJECT_PACK_ORDERfor_each_object_in_pack().
デリック・ストーリーはそうしました Windowsでの彼自身のテスト 高度な精度で2%の改善を示します。


GIT 2.23(2019年第3四半期)が改善します "git rev-list --objects「学んだ」--no-object-names「パックオブジェクトのグループ化ヒントとして使用されるオブジェクトへのパスを抑えるオプション。

見る コミット42357b4 (2019年6月19日) エミリー・シャファー(nasamuffin).
(融合 Junio C Hamano- gitster --F4F7E75をコミットします, 、2019年7月9日)

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

簡単に解析できるようにします cat-file Rev-Listに、追加情報なしで非コミュニティオブジェクトのOIDのみを印刷するオプションを提供することにより。
これは短期シムです。後で、 rev-list 見つけたオブジェクトの種類を印刷する方法を教えてください cat-file's。

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

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 verify-pack -v <packfile>

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top