gitインデックスには正確に何が含まれていますか?


178

Gitインデックスには正確に何が含まれ、インデックスのコンテンツを表示するためにどのコマンドを使用できますか?


更新

すべての回答ありがとうございます。インデックスはステージング領域として機能し、コミットされるのは作業ツリーではなくインデックス内にあることを知っています。インデックスオブジェクトの構成について知りたいだけです。ファイル名/ディレクトリ名、SHA-1ペアのリスト、一種の仮想ツリーかもしれませんね。

Git用語で、インデックスの内容を一覧表示するために使用できる配管コマンドはありますか?



3
ダイアグラムを読んで見る必要があります-非常に役立ちます: gitguys.com/topics/whats-the-deal-with-the-git-index
kernix

1
@kernixドメインの有効期限が切れています。あまり役に立ちません。
narendra-choudhary

回答:


162

Gitブックには、インデックスの内容に関する記事が含まれています

インデックスは.git/index、それぞれに権限とBLOBオブジェクトのSHA1を持つパス名のソートされたリストを含むバイナリファイル(通常はに保持)です。git ls-filesインデックスの内容を表示できます:

$ git ls-files --stage
100644 63c918c667fa005ff12ad89437f2fdc80926e21c 0   .gitignore
100644 5529b198e8d14decbe4ad99db3f7fb632de0439d 0   .mailmap

レーシーのGitの問題は、その構造上のいくつかの詳細を与えます:

インデックスはgitで最も重要なデータ構造の1つです。
パスとそのオブジェクト名のリストを記録することで仮想作業ツリーの状態を表し、コミットされる次のツリーオブジェクトを書き出すためのステージング領域として機能します。
状態は、必ずしも作業ツリー内のファイルと一致する必要はなく、多くの場合一致しないという意味で「仮想」です。


詳しくは、cf。" git / git / Documentation / technical / index-format.txt ":

Gitインデックスファイルの形式は次のとおりです。

すべての2進数はネットワークバイト順です。特に明記されていない限り、ここでは
バージョン2について説明します。

  • 以下で構成される12バイトのヘッダー:
    • 4バイトの署名
      署名は{' D'、 ' I'、 ' R'、 ' C'}( " dircache"の略)
    • 4バイトのバージョン番号
      現在サポートされているバージョンは2、3、4です。
    • 32ビットのインデックスエントリ数。
  • ソートされたインデックスエントリの数。
  • 拡張機能
    拡張機能は署名によって識別されます。
    オプションの拡張機能は、Gitが理解できない場合は無視できます。
    Gitは現在、キャッシュされたツリーをサポートし、元に戻す拡張機能を解決します。
    • 4バイトの拡張署名。最初のバイトが ' A' .. ' Z'の場合、拡張子はオプションであり、無視できます。
    • 拡張の32ビットサイズ
    • 拡張データ
  • このチェックサムの前のインデックスファイルのコンテンツに対する160ビットSHA-1。

mljrg コメント

インデックスが次のコミットが準備される場所である場合、コミットgit ls-files -s後に「」が何も返さないのはなぜですか?

インデックスは追跡対象を表し、コミットの直後ので追跡対象は最後のコミットと同じです(git diff --cached何も返しません)。

だから、git ls-files -sすべてのファイルを追跡リスト(オブジェクト名、モードビットと出力の段数)。

(追跡される要素の)そのリストは、コミットの内容で初期化されます。
ブランチを切り替えると、インデックスの内容は、切り替えたブランチが参照するコミットにリセットされます。


Git 2.20(2018年第4四半期)には、インデックスエントリオフセットテーブル(IEOT)が追加されています

参照77ff112をコミットし3255089をコミットしabb4bb8をコミットしc780b9cをコミットし3b1d9e0をコミットし371ed0dコミットにより(2018年10月10日)のベン・ピート(benpeart
参照してください252d079コミットにより(2018年9月26日)のグエンタイ・ゴックDuyと(pclouds
(合併によりJunio C浜野- gitster-コミットe27bfaa、2018年10月19日)

ieot:インデックスエントリオフセットテーブル(IEOT)拡張機能を追加

このパッチは、追加のデータをインデックスに追加することにより、インデックスのロードのCPUコストに対処できるようにし、キャッシュエントリのロードと変換を効率的にマルチスレッド化できるようにします。

これは、インデックスファイル内のキャッシュエントリのブロックへのオフセットのテーブルである(オプションの)インデックス拡張を追加することで実現します。

これをV4インデックスで機能させるために、キャッシュエントリを書き込むときに、前のエントリのパス名が完全に異なるかのように現在のエントリをエンコードすることにより、プレフィックス圧縮を定期的に「リセット」し、IEOTにそのエントリのオフセットを保存します。 。
基本的に、V4インデックスでは、プレフィックス圧縮エントリのブロックにオフセットを生成します。

新しいindex.threadsコンフィグ設定、インデックスのロードは高速化されました。


その結果(IEOTを使用して)、7bd9631をコミットし、read-cache.c load_cache_entries_threaded()Git 2.23(2019年第3四半期)の関数をクリーンアップします。

参照してください。8373037コミットd713e88をコミットしd92349dをコミットし113c29aをコミットしコミットc95fc727a2a721をコミットしc016579をコミットしコミットbe27fb713a1781をコミットし7bd9631をコミットし3c1dce8をコミットしcf7a901をコミットしd64db5bコミット76a7bc0コミットにより(2019年5月9日)のジェフ・キング(peff
(合併によりJunio C浜野- gitster-コミットc0e78f7、2019年6月13日)

読み取りキャッシュ:スレッド化されたロードから未使用のパラメーターを削除

このload_cache_entries_threaded()関数は、src_offset使用しないパラメーターを取ります。これは77ff112read-cache:ワーカースレッドでのキャッシュエントリのロード、2018-10-10、Git v2.20.0-rc0)の登場以来存在しています。

メーリングリストを掘り下げて、そのパラメーターはシリーズの初期のイテレーションの一部でしたが、コードがIEOT拡張機能の使用に切り替えられたときに不要になりました。


6
Gitモデルのインデックスの重要性については、stackoverflow.com
questions / 1450348 /…を

上記の最初のリンクは、インデックスに記事がないgit-scmのバージョンを指しています。意図はここを指すことだったと思います:schacon.github.io/gitbook/7_the_git_index.html
Kris

1
@KrisGiesingリンクありがとうございます。答えを更新しました。
VonC 2013

@VonCインデックスが次のコミットが準備される場所である場合、「git ls-files -s」がコミット後に何も返さないのはなぜですか?あなたがあなたの答えに入れた以上に、インデックスについて何かがあるはずです。
mljrg 14

@mljrg私があなたをフォローしているのかわかりません:コミットの、(コミットが準備されていた)ステージは空になります。コミットが行われたからですよね。
VonC 2014

62

ビットごとの分析

フォーマットをよりよく理解し、いくつかのフィールドをより詳細に調査するために、少しテストを行うことにしました。

以下の結果はGitバージョン1.8.5.2とで同じです2.3

わからない/見つからないポイントをマークしましたTODO。これらのポイントを自由に補完してください。

他の人が述べたように、インデックスは.git/index標準のツリーオブジェクトとしてではなくの下に保存され、その形式はバイナリであり、https//github.com/git/git/blob/master/Documentation/technical/index-formatにドキュメント化されています。 txt

インデックスはコミットを作成するためのキャッシュであるため、インデックスを定義する主要な構造体はcache.hにあります。

セットアップ

次のコマンドでテストリポジトリを開始すると、

git init
echo a > b
git add b
tree --charset=ascii

.gitディレクトリのルックスが好き:

.git/objects/
|-- 78
|   `-- 981922613b2afb6025042ff6bd878ac1994e85
|-- info
`-- pack

そして、唯一のオブジェクトのコンテンツを取得する場合:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

我々が得ますa。これは次のことを示しています。

  • blobオブジェクトが作成されてindexからのファイル内容へのポイントgit add b
  • メタデータは、ツリーオブジェクトではなくインデックスファイルに保存されます。これは、オブジェクトが1つしかないためです。ブロブ(通常のGitオブジェクトでは、ブロブメタデータはツリーに保存されます)

hd分析

次に、インデックス自体を見てみましょう。

hd .git/index

与える:

00000000  44 49 52 43 00 00 00 02  00 00 00 01 54 09 76 e6  |DIRC.... ....T.v.|
00000010  1d 81 6f c6 54 09 76 e6  1d 81 6f c6 00 00 08 05  |..o.T.v. ..o.....|
00000020  00 e4 2e 76 00 00 81 a4  00 00 03 e8 00 00 03 e8  |...v.... ........|
00000030  00 00 00 02 78 98 19 22  61 3b 2a fb 60 25 04 2f  |....x.." a;*.`%./|
00000040  f6 bd 87 8a c1 99 4e 85  00 01 62 00 ee 33 c0 3a  |......N. ..b..3.:|
00000050  be 41 4b 1f d7 1d 33 a9  da d4 93 9a 09 ab 49 94  |.AK...3. ......I.|
00000060

次に結論します:

  | 0           | 4            | 8           | C              |
  |-------------|--------------|-------------|----------------|
0 | DIRC        | Version      | File count  | ctime       ...| 0
  | ...         | mtime                      | device         |
2 | inode       | mode         | UID         | GID            | 2
  | File size   | Entry SHA-1                              ...|
4 | ...                        | Flags       | Index SHA-1 ...| 4
  | ...                                                       |

最初に来るのは、次の場所で定義されたヘッダーです。struct cache_header

  • 44 49 52 43DIRC。TODO:なぜこれが必要なのですか?

  • 00 00 00 02:形式バージョン:2.インデックス形式は時間とともに進化しました。現在、4までのバージョンが存在します。GitHub上の異なるコンピューター間でコラボレーションする場合、ベアリポジトリにはインデックスが格納されないため、インデックスの形式は問題になりません。インデックスはクローン時に生成されます。

  • 00 00 00 01:インデックス上のファイルの数:ちょうど1、 b

次に、struct cache_entryで定義されたインデックスエントリのリストを開始します。ここでは1つだけです。を含む:

  • 一連のファイルメタデータ:8バイトctime、8バイトmtime、4バイト:デバイス、iノード、モード、UID、GID。

    方法に注意してください:

    • ctimeそして、mtime(同じです54 09 76 e6 1d 81 6f c6私たちは、ファイルを変更していないので、予想通り)

      最初のバイトは、16進数のEPOCHからの秒数です。

      date --date="@$(printf "%x" "540976e6")"
      

      与える:

      Fri Sep  5 10:40:06 CEST 2014
      

      これは私がこの例を作ったときです。

      次の4バイトはナノ秒です。

    • UIDとGIDは00 00 03 e8、16進数で1000です。これは、シングルユーザーセットアップの一般的な値です。

    このメタデータのほとんどはツリーオブジェクトに存在しないため、Gitは内容全体を比較することなく、ファイルがすばやく変更されたかどうかを確認できます。

  • 行の先頭に3000 00 00 02:ファイルサイズ:2バイト(a\nからecho

  • 78 98 19 22 ... c1 99 4e 85:エントリの以前のコンテンツを超える20バイトのSHA-1。有効フラグを想定する私の実験によるとそれに続くフラグはこのSHA-1では考慮されないことに注意してください。

  • 2バイトのフラグ: 00 01

    • 1ビット:有効なフラグと見なします。私の調査では、この名前の付いていないフラグがgit update-index --assume-unchangedその状態を保存する場所であることが示されていますhttps : //stackoverflow.com/a/28657085/895245

    • 1ビット拡張フラグ。拡張フラグが存在するかどうかを決定します。0拡張フラグを持たないバージョン2でなければなりません。

    • マージ中に使用される2ビットのステージフラグ。ステージは次の場所に記載されていman git-mergeます。

      • 0:マージ競合ではない通常のファイル
      • 1: ベース
      • 2: 私たちのもの
      • 3:彼らのもの

      マージの競合中、1〜3のすべてのステージがインデックスに格納され、などの操作が可能になりますgit checkout --ours

      の場合git add、ステージ0がパスのインデックスに追加され、Gitは競合が解決済みとしてマークされていることを認識します。TODO:これを確認してください。

    • たどるパスの12ビット長0 01::パスがあったため、1バイトのみb

  • 2バイトの拡張フラグ。「拡張フラグ」が基本フラグに設定されている場合にのみ意味があります。TODO。

  • 62(ASCII b):可変長パス。前のフラグで決定された長さ、ここでは1バイトのみb

次に00、パスがnullで終了し、インデックスが8バイトの倍数で終了するように、1〜8バイトのゼロパディングがあります。これは、インデックスバージョン4以前にのみ発生します。

拡張機能は使用されませんでした。ファイルにチェックサム用の十分なスペースが残っていないため、Gitはこれを認識しています。

最後にee 33 c0 3a .. 09 ab 49 94、インデックスの内容に対して20バイトのチェックサムがあります。


1
とても興味深い。+1。それは私自身の答えをうまく示しいます。これらの結果は最新のGit 2.1+で変更されるのでしょうか。
VonC、2014

3
@NielsBomはい、それもうまくいきます。プログラムを解釈するとき、私は2つのアプローチを取ることを好みます。最初に、プログラムが生成する出力を確認するために経験的であり、次にソースを読み取るだけです。そうしないと、単純な出力にさえ現れないソースコードのエッジケースに巻き込まれるかもしれません。もちろん、私は私をガイドするためにソース構造を調べました、そしてすべてのTODOはそれらの構造がどのように操作されるかを読んで解決することができます。これは難しい部分です。
Ciro Santilli郝海东冠状病六四事件法轮功

1
@CiroSantilli六四事件法轮功纳米比亚威视:16進エディタでインデックスを変更して20バイトのチェックサムを更新した場合、他のオブジェクトに保存されているsha1を更新するコマンドはありますか?(gitは、インデックスのsha1署名が破損していると警告します)。また、pushリクエストを介して送信される場合、インデックスデータはまったく異なる方法で格納されます。
user2284570

1
@CiroSantilli六四事件法轮功纳米比亚威视:セキュリティ目的。よく知られている種類のラスターイメージファイル攻撃をgitデータベース/オブジェクトに適用するだけを探しています。(もちろん、ほとんどの実装が最近その視点に注意を払っていることを知っていますが、おそらくすべてではありません)  したがって、特に配列の長さを示すバイナリデータ構造を検索しています。(テキストバッファに関しては、null終了が行数を伝えるための標準であると思われます)
user2284570

1
に関してはgit add、あなたのTODOとおり:あなたは正しいです。特定のパスに高ステージインデックスエントリ(競合)がある場合、git addそのパスを使用すると、すべての高ステージインデックスエントリが削除され、作業ディレクトリのコピーがステージに追加され0ます。(競合の解決)。
エドワードトムソン

11

Gitインデックスは、作業ディレクトリとリポジトリの間のステージング領域です。インデックスを使用して、一緒にコミットする一連の変更を構築できます。コミットを作成すると、コミットされるのは現在このインデックスにあるものであり、作業ディレクトリにあるものではありません。

インデックスの内容を確認するには、次のコマンドを発行します。

git status

git statusを実行すると、ステージングされているファイル(現在はインデックス内)、変更されているがまだステージングされていないファイル、完全に追跡されていないファイルを確認できます。

あなたはこれを読むことができます。グーグル検索は多くのリンクを投げます、そしてそれはかなり十分であるはずです。


7
git statusインデックスからすべてのファイルをリストするわけではありません。インデックスと作業ディレクトリの間で異なるファイルのみをリストします。インデックス内のすべてのファイルを表示するには、を使用する必要がありますgit ls-files
Akash Agrawal 14

1
@AkashAgrawalは、インデックスとworkdirで異なるかどうかに関係なく、実際にgit status インデックスファイルをリストします。
Acumenus 2014年

3
はい、いくつかのインデックスファイルが一覧表示されますが、インデックス内にあるすべてのものは表示されません。これは、箱の中に2つの緑色のボールと3つの赤いボールがあると言うようなものです。箱の中身を確認するには、2つの緑色のボールを引き出します。Akashが言ったことは最も正確です。インデックス内のすべてのファイルを表示するには、git ls-filesを使用します。
dave4jr 2016年

3
確かに。 git statusはい、インデックス内のファイルを一覧表示ますが、インデックス内のすべてのファイルは一覧表示しません。git status 実際にどのよう機能するかを説明することは、おそらくこれではないかもしれませんが、いくつかの質問に対する有益な回答になります。
エドワードトムソン

1
git status作業ツリーのステータス(作業ツリーとインデックスの違い)を示します。実際にはインデックスは表示されません。git-scm.com/docs/git-status
wisbucky

1

これがまさに必要なものです。このコマンドを使用してください。

$ binwalk index

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
1717          0x6B5           Unix path: /company/user/user/delete.php
1813          0x715           Unix path: /company/user/user/get.php
1909          0x775           Unix path: /company/user/user/post.php
2005          0x7D5           Unix path: /company/user/user/put.php
3373          0xD2D           Unix path: /urban-airship/channel/channel/post.php
3789          0xECD           Unix path: /urban-airship/named-user/named-user/post.php
3901          0xF3D           Unix path: /user/categories/categories/delete.php
4005          0xFA5           Unix path: /user/categories/categories/get.php
4109          0x100D          Unix path: /user/categories/categories/put.php
4309          0x10D5          Unix path: /user/favorites/favorites/delete.php

0

Gitインデックスは、.git/indexパス名のソートされたリストを含むバイナリファイル(通常はに保持)であり、それぞれに権限とBLOBオブジェクトのSHA1が付いています。

git ls-filesインデックスの内容を表示できます。その言葉に注意してくださいindexstagecacheGitの中に同じものです:彼らは交換可能に使用されます。

ここに画像の説明を入力してください

Gitインデックス、つまりGitキャッシュには、3つの重要なプロパティがあります。

  1. インデックスには、単一の(一意に決定された)ツリーオブジェクトを生成するために必要なすべての情報が含まれています。
  2. インデックスは、それが定義するツリーオブジェクトと作業ツリー間の高速比較を可能にします。
  3. 異なるツリーオブジェクト間のマージの競合に関する情報を効率的に表すことができ、各パス名を、ツリー間の3者間マージを作成できる関連ツリーに関する十分な情報に関連付けることができます。

出典

  1. https://mincong.io/2018/04/28/git-index/
  2. https://medium.com/hackernoon/understanding-git-index-4821a0765cf
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.