webentwicklung-frage-antwort-db.com.de

Was enthält der Git-Index genau?

Was enthält der Git-Index genau und mit welchem ​​Befehl kann ich den Inhalt des Index anzeigen?


pdate

Vielen Dank für alle Ihre Antworten. Ich weiß, dass der Index als Staging-Bereich fungiert und das Festgeschriebene im Index und nicht im Arbeitsbaum enthalten ist. Ich bin nur gespannt, woraus ein Indexobjekt besteht. Ich vermute, es könnte eine Liste von Dateinamen/Verzeichnisnamen, SHA-1-Paaren oder eine Art virtueller Baum sein?

Gibt es in der Git-Terminologie einen Installationsbefehl , mit dem ich den Inhalt des Index auflisten kann?

165
mochidino

Das Git-Buch enthält einen Artikel über was ein Index enthält :

Der Index ist eine Binärdatei (normalerweise in .git/index), Die eine sortierte Liste von Pfadnamen enthält, die jeweils über Berechtigungen verfügen, und die SHA1 eines Blob-Objekts enthält. git ls-files Kann Ihnen den Inhalt des Index anzeigen:

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

Das Rassiges Git-Problem gibt einige weitere Details zu dieser Struktur:

Der Index ist eine der wichtigsten Datenstrukturen in Git.
Es repräsentiert einen virtuellen Arbeitsbaumstatus, indem es eine Liste von Pfaden und deren Objektnamen aufzeichnet und als Bereitstellungsbereich zum Ausschreiben des nächsten festzuschreibenden Baumobjekts dient.
Der Status ist "virtuell" in dem Sinne, dass er nicht unbedingt mit den Dateien im Arbeitsbaum übereinstimmen muss und oft nicht übereinstimmt.


Um mehr zu sehen, vgl. " git/git/Documentation/technical/index-format.txt ":

Die Git-Indexdatei hat das folgende Format

Alle Binärzahlen sind in der Reihenfolge der Netzwerkbytes.
Version 2 wird hier beschrieben, sofern nicht anders angegeben.

  • Ein 12-Byte-Header bestehend aus:
    • 4-Byte-Signatur :
      Die Signatur ist {'D', 'I', 'R', 'C'} (steht für "dircache ")
    • 4-Byte-Versionsnummer :
      Die aktuell unterstützten Versionen sind 2, 3 und 4.
    • 32-Bit-Anzahl von Indexeinträgen.
  • Eine Anzahl von sortierten Indexeinträgen.
  • Erweiterungen :
    Erweiterungen werden durch Unterschrift gekennzeichnet.
    Optionale Erweiterungen können ignoriert werden, wenn Git sie nicht versteht.
    Git unterstützt derzeit zwischengespeicherten Baum und löst rückgängig gemachte Erweiterungen auf.
    • 4-Byte-Erweiterungssignatur. Wenn das erste Byte 'A'..'Z' ist, ist die Erweiterung optional und kann ignoriert werden.
    • 32-Bit-Größe der Erweiterung
    • Erweiterungsdaten
  • 160-Bit-SHA-1 über den Inhalt der Indexdatei vor dieser Prüfsumme.

mljrgKommentare :

Wenn der Index der Ort ist, an dem das nächste Commit vorbereitet wird, warum gibt "git ls-files -s" Nach dem Commit nichts zurück?

Da der Index darstellt, was verfolgt wird und was unmittelbar nach einem Commit verfolgt wird, ist identisch mit dem letzten Commit (git diff --cached gibt nichts zurück).

Also listet git ls-files -s Alle verfolgten Dateien auf (Objektname, Modusbits und Stufennummer in der Ausgabe).

Diese Liste (des verfolgten Elements) wird mit dem Inhalt eines Commits initialisiert.
Wenn Sie den Zweig wechseln, wird der Indexinhalt auf das Commit zurückgesetzt, auf das der Zweig verweist, zu dem Sie gerade gewechselt haben.


Git 2.20 (Q4 2018) fügt eine Index Entry Offset Table (IEOT) hinzu :

Siehe Festschreiben 77ff112 , Festschreiben 3255089 , Festschreiben abb4bb8 , Festschreiben c780b9c , Festschreiben 3b1d9e , commit 371ed0d (10. Oktober 2018) von Ben Peart (benpeart) .
Siehe Festschreiben 252d079 (26. September 2018) von Nguyễn Thái Ngọc Duy (pclouds .
(Zusammengeführt von Junio ​​C Hamano - gitster - in Festschreiben von e27bfaa , 19. Oktober 2018)

ieot: Fügen Sie die IEOT-Erweiterung (Index Entry Offset Table) hinzu

Mit diesem Patch können die CPU-Kosten für das Laden des Indexes behoben werden, indem dem Index zusätzliche Daten hinzugefügt werden, die es uns ermöglichen, das Laden und die Konvertierung von Cache-Einträgen effizient zu multithreaden.

Dies wird durch Hinzufügen einer (optionalen) Indexerweiterung erreicht, die eine Tabelle mit Offsets zu Blöcken von Cache-Einträgen in der Indexdatei darstellt.

Damit dies für V4-Indizes funktioniert, wird beim Schreiben der Cache-Einträge die Präfix-Komprimierung regelmäßig "zurückgesetzt", indem der aktuelle Eintrag so codiert wird, als ob der Pfadname für den vorherigen Eintrag völlig anders wäre, und der Offset dieses Eintrags im IEOT gespeichert .
Grundsätzlich werden mit V4-Indizes Offsets in Blöcken von präfixkomprimierten Einträgen generiert.

Mit der Einstellung new index.threads config wird der Index jetzt schneller geladen.


Als Ergebnis ( bei Verwendung von IEOT ), Festschreiben 7bd9631 bereinigen Sie die Funktion read-cache.c load_cache_entries_threaded() für Git 2.23 (Q3 2019).

Siehe Festschreiben 8373037 , Festschreiben d713e88 , Festschreiben d92349d , Festschreiben 113c29a , Festschreiben c95fc72 , Festschreiben 7a2a721 , Festschreiben c016579 , Festschreiben be27fb7 , Festschreiben 13a1781 , Festschreiben 7bd9631 , commit 3c1dce8 , commit cf7a901 , commit d64db5b , commit 76a7bc (09. Mai 2019) bis Jeff King (peff) .
(Zusammengeführt von Junio ​​C Hamano - gitster - in Festschreiben von c0e78f7 , 13. Juni 2019)

lese-Cache: Lösche nicht benutzte Parameter von der Thread-Last

Die load_cache_entries_threaded() -Funktion verwendet einen src_offset - Parameter, den sie nicht verwendet. Dies gibt es seit seiner Einführung in 77ff112 (read-cache: Cache-Einträge in Worker-Threads laden, 2018-10-10, Git v2.20.0-rc0).

Dieser Parameter befand sich in der Mailingliste und war Teil einer früheren Iteration der Reihe , wurde jedoch unnötig, als der Code auf die IEOT-Erweiterung umstellte.

147
VonC

Stück für Stück Analyse

Ich habe beschlossen, ein wenig zu testen, um das Format besser zu verstehen und einige der Felder genauer zu untersuchen.

Die folgenden Ergebnisse sind für Git-Versionen 1.8.5.2 Und 2.3 Gleich.

Ich habe Punkte markiert, die ich mit TODO nicht sicher/nicht gefunden habe: Bitte ergänzen Sie diese Punkte.

Wie bereits erwähnt, wird der Index unter .git/index Und nicht als Standardbaumobjekt gespeichert. Das Format ist binär und dokumentiert unter: https://github.com/git/git/blob/ master/Documentation/technical/index-format.txt

Die wichtigsten Strukturen, die den Index definieren, befinden sich unter cache.h , da der Index ein Cache zum Erstellen von Commits ist.

Installieren

Wenn wir ein Test-Repository starten mit:

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

Das Verzeichnis .git Sieht folgendermaßen aus:

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

Und wenn wir den Inhalt des einzigen Objekts erhalten:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Wir bekommen a. Dies zeigt an, dass:

  • das index zeigt auf den Dateiinhalt, da git add b ein Blob-Objekt erzeugt hat
  • es speichert die Metadaten in der Indexdatei und nicht in einem Baumobjekt, da es nur ein einziges Objekt gab: den Blob (bei normalen Git-Objekten werden Blob-Metadaten im Baum gespeichert).

hD-Analyse

Betrachten wir nun den Index selbst:

hd .git/index

Gibt:

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

Als nächstes werden wir schließen:

  | 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
  | ...                                                       |

Zuerst kommt der Header, definiert unter: struct cache_header :

  • 44 49 52 43: DIRC. TODO: warum ist das notwendig?

  • 00 00 00 02: Formatversion: 2. Das Indexformat hat sich im Laufe der Zeit weiterentwickelt. Derzeit gibt es eine Version bis 4. Das Format des Index sollte bei der Zusammenarbeit zwischen verschiedenen Computern auf GitHub kein Problem sein, da in leeren Repositorys der Index nicht gespeichert wird: Er wird zum Zeitpunkt des Klons generiert.

  • 00 00 00 01: Anzahl der Dateien im Index: nur eine, b.

Als nächstes startet eine Liste von Indexeinträgen, definiert durch struct cache_entry Hier haben wir nur einen. Es beinhaltet:

  • eine Reihe von Dateimetadaten: 8 Byte ctime, 8 Byte mtime, dann 4 Byte: Gerät, Inode, Modus, UID und GID.

    Beachten Sie, wie:

    • ctime und mtime stimmen erwartungsgemäß überein (54 09 76 e6 1d 81 6f c6), da wir die Datei nicht geändert haben

      Die ersten Bytes sind Sekunden seit Epoche in hex:

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

      Gibt:

      Fri Sep  5 10:40:06 CEST 2014
      

      In diesem Fall habe ich dieses Beispiel gemacht.

      Die zweiten 4 Bytes sind Nanosekunden.

    • UID und GID sind 00 00 03 e8, 1000 in hex: ein allgemeiner Wert für Einzelbenutzer-Setups.

    Mit all diesen Metadaten, von denen die meisten in Baumobjekten nicht vorhanden sind, kann Git prüfen, ob sich eine Datei schnell geändert hat, ohne den gesamten Inhalt zu vergleichen.

  • am Anfang der Zeile 30: 00 00 00 02: Dateigröße: 2 Byte (a und \n von echo)

  • 78 98 19 22 ... c1 99 4e 85: 20 Byte SHA-1 über dem vorherigen Inhalt des Eintrags. Beachten Sie, dass gemäß meine Experimente mit der Annahme eines gültigen Flags die darauf folgenden Flags in diesem SHA-1 nicht berücksichtigt werden.

  • 2-Byte-Flags: 00 01

    • 1 Bit: Gültiges Flag annehmen. Meine Untersuchungen haben ergeben, dass in dieser schlecht benannten Flagge der Status von git update-index --assume-unchanged Gespeichert ist: https://stackoverflow.com/a/28657085/895245

    • 1 Bit erweitertes Flag. Bestimmt, ob die erweiterten Flags vorhanden sind oder nicht. Muss in Version 2, die keine erweiterten Flags hat, 0 Sein.

    • 2-Bit-Stage-Flag, das während der Zusammenführung verwendet wird. Stufen sind dokumentiert in man git-merge:

      • 0: Reguläre Datei, kein Zusammenführungskonflikt
      • 1: Basis
      • 2: Unsere
      • 3: Ihnen

      Während eines Zusammenführungskonflikts werden alle Stufen von 1-3 im Index gespeichert, um Operationen wie git checkout --ours Zu ermöglichen.

      Wenn Sie git add, Wird dem Index für den Pfad eine Stufe 0 hinzugefügt, und Git weiß, dass der Konflikt als gelöst markiert wurde. TODO: Überprüfen Sie dies.

    • 12-Bit-Länge des Pfades, der folgen wird: 0 01: 1 Byte nur, da der Pfad b war

  • 2 Byte erweiterte Flags. Nur sinnvoll, wenn bei den Basisflags das "Extended Flag" gesetzt wurde. MACHEN.

  • 62 (ASCII b): Pfad variabler Länge. Länge in den vorherigen Flags bestimmt, hier nur 1 Byte, b.

Dann kommt ein 00: 1-8 Bytes mit Null-Auffüllung, so dass der Pfad mit Null abgeschlossen wird und der Index mit einem Vielfachen von 8 Bytes endet. Dies geschieht nur vor der Indexversion 4.

Es wurden keine Erweiterungen verwendet. Git weiß das, weil in der Datei nicht mehr genügend Speicherplatz für die Prüfsumme vorhanden wäre.

Schließlich gibt es eine 20-Byte-Prüfsumme ee 33 c0 3a .. 09 ab 49 94 Über dem Inhalt des Index.

Der Git-Index ist ein Staging-Bereich zwischen Ihrem Arbeitsverzeichnis und Ihrem Repository. Sie können den Index verwenden, um eine Reihe von Änderungen zu erstellen, die Sie gemeinsam festschreiben möchten. Wenn Sie ein Commit erstellen, wird das Commit ausgeführt, was sich derzeit in diesem Index befindet, nicht das, was sich in Ihrem Arbeitsverzeichnis befindet.

Um zu sehen, was sich im Index befindet, geben Sie den folgenden Befehl ein:

git status

Wenn Sie git status ausführen, können Sie sehen, welche Dateien (derzeit in Ihrem Index) gespeichert sind, welche geändert, aber noch nicht gespeichert wurden und welche nicht verfolgt werden.

Sie können lesen dies . Eine Google-Suche wirft viele Links auf, die ziemlich autark sein sollten.

12
user225312

Verwenden Sie diesen Befehl, um genau das zu tun, was Sie benötigen.

$ 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
1
l h