231 Stimmen

Was enthält der Git-Index EXAKT?

Was enthält der Git-Index genau, und mit welchem Befehl kann ich den Inhalt des Indexes einsehen?


Vielen Dank für all Ihre Antworten. Ich weiß, dass der Index als Staging-Bereich fungiert, und dass das, was übertragen wird, im Index und nicht im Arbeitsbaum gespeichert wird. Ich bin nur neugierig, woraus ein Indexobjekt besteht. Ich vermute, es könnte eine Liste von Dateinamen/Verzeichnisnamen sein, SHA-1-Paare, vielleicht eine Art virtueller Baum?

Gibt es, in der Git-Terminologie, irgendwelche Klempnerarbeiten Befehl, mit dem ich den Inhalt des Indexes auflisten kann?

209voto

VonC Punkte 1117238

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

Der Index ist eine Binärdatei (im Allgemeinen in .git/index ) mit einer sortierten Liste von Pfadnamen, jeweils mit Berechtigungen und dem SHA1-Wert eines Blob-Objekts; git ls-files kann Ihnen den Inhalt des Indexes anzeigen:

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

El Rasantes Git-Problem enthält einige weitere Einzelheiten zu dieser Struktur:

Der Index ist eine der wichtigsten Datenstrukturen in Git.
Er repräsentiert einen virtuellen Arbeitsbaumzustand durch die Aufzeichnung einer Liste von Pfaden und deren Objektnamen und dient als Staging Area, um das nächste zu übertragende Baumobjekt zu schreiben.
Der Status ist "virtuell" in dem Sinne, dass er nicht unbedingt mit den Dateien im Arbeitsbaum übereinstimmen muss und dies oft auch nicht tut.


Nov. 2021: siehe auch " Mit dem spärlichen Index von Git kann sich dein Monorepo klein fühlen " aus Derrick Stolee (Microsoft/GitHub)

https://github.blog/wp-content/uploads/2021/11/Fig-1-working-directory-index-commit-history.png

Der Git-Index ist eine wichtige Datenstruktur in Git. Er dient als "Staging Area" zwischen den Dateien auf Ihrem Dateisystem und Ihrem Commit-Verlauf.

  • Wenn Sie git add werden die Dateien aus Ihrem Arbeitsverzeichnis mit einem Hashwert versehen und als Objekte im Index gespeichert, so dass es sich um "abgestufte Änderungen" handelt.
  • Wenn Sie git commit werden die im Index gespeicherten abgestuften Änderungen verwendet, um die neue Übertragung zu erstellen.
  • Wenn Sie git checkout Git nimmt die Daten aus einer Übertragung und schreibt sie in das Arbeitsverzeichnis und den Index.

Der Index speichert nicht nur Ihre abgestuften Änderungen, sondern auch Dateisysteminformationen über Ihr Arbeitsverzeichnis.
Dadurch kann Git geänderte Dateien schneller melden.


Weitere Informationen finden Sie unter ". git/git/Dokumentation/technisch/index-format.txt ":

Die Git-Indexdatei hat das folgende Format

Alle Binärzahlen sind in Netzwerk-Byte-Reihenfolge.
Version 2 wird hier beschrieben, wenn nicht anders angegeben.

  • Ein 12-Byte-Header, bestehend aus:
  • 4 Byte Unterschrift :
    Die Signatur lautet { ' D ', ' I ', ' R ', ' C ' } (steht für " dircache ")
  • 4 Byte Versionsnummer :
    Die derzeit unterstützten Versionen sind 2, 3 und 4.
  • 32-Bit-Anzahl der Indexeinträge.
  • Eine Reihe von sortierten Index-Einträge .
  • Erweiterungen :
    Erweiterungen werden durch eine Signatur gekennzeichnet.
    Optionale Erweiterungen können ignoriert werden, wenn Git sie nicht versteht.
    Git unterstützt derzeit gecachte Tree- und Resolve-Rückgängig-Erweiterungen.
  • 4-Byte-Erweiterungssignatur. Ist das erste Byte ' A '..' Z ' ist die Erweiterung optional und kann ignoriert werden.
  • 32-Bit-Größe der Erweiterung
  • Daten zur Erweiterung
  • 160-bit SHA-1 über den Inhalt der Indexdatei vor dieser Prüfsumme.

mljrg Kommentare :

Wenn der Index der Ort ist, an dem die nächste Übertragung vorbereitet wird, warum wird dann nicht " git ls-files -s " nach der Übergabe nichts zurückgeben?

Denn der Index stellt dar, was verfolgt wird und direkt nach einer Übergabe ist das, was verfolgt wird, identisch mit der letzten Übergabe ( git diff --cached gibt nichts zurück).

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

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


Git 2.20 (Q4 2018) fügt eine Indexeintrag-Offset-Tabelle (IEOT) :

Ver 77ff112 übertragen , Commit 3255089 , abb4bb8 übergeben , c780b9c übergeben , Übergabe 3b1d9e0 , 371ed0d übergeben (10. Okt. 2018) von Ben Peart ( benpeart ) .
Siehe 252d079 festlegen (26. Sep. 2018) von Nguyen Thái Ngoc Duy ( pclouds ) .
(Zusammengefasst von Junio C. Hamano -- gitster -- en e27bfaa übergeben , 19. Okt. 2018)

ieot: Index Entry Offset Table (IEOT) Erweiterung hinzufügen

Dieser Patch ermöglicht es, die CPU-Kosten für das Laden des Indexes durch Hinzufügen von zusätzliche Daten zum Index hinzugefügt werden, die es uns ermöglichen, das das Laden und die Konvertierung von Cache-Einträgen effizient mit mehreren Threads durchzuführen.

Dies wird erreicht, indem eine (optionale) Indexerweiterung hinzugefügt wird, die eine Tabelle mit Offsets zu Blöcken von Cache-Einträgen in der Indexdatei.

Damit dies für V4-Indizes funktioniert, wird beim Schreiben der Cache-Einträge die Präfix-Komprimierung periodisch "zurückgesetzt", indem der aktuelle Eintrag so kodiert wird, als ob der Pfadname des vorherigen Eintrags völlig anders wäre, und der Offset dieses Eintrags im IEOT.
Grundsätzlich werden bei V4-Indizes Offsets in Blöcken von präfix-komprimierten Einträgen erzeugt.

Mit dem neue index.threads-Konfigurationseinstellung ist das Laden des Index jetzt schneller.


Infolgedessen ( der Verwendung von IEOT ), 7bd9631 festlegen Bereinigung der read-cache.c load_cache_entries_threaded() Funktion für Git 2.23 (Q3 2019).

Ver festlegen 8373037 , Übergabe d713e88 , Übergabe d92349d , Übergabe 113c29a , c95fc72 übergeben , 7a2a721 festlegen , c016579 festlegen , be27fb7 übergeben , Commit 13a1781 , 7bd9631 festlegen , 3c1dce8 festlegen , cf7a901 festlegen , Übergabe d64db5b , Übergabe 76a7bc0 (09. Mai 2019) von Jeff King ( peff ) .
(Zusammengefasst von Junio C. Hamano -- gitster -- en c0e78f7 übergeben , 13. Juni 2019)

read-cache: unbenutzte Parameter aus threaded load entfernen

El load_cache_entries_threaded() Funktion nimmt eine src_offset Parameter der nicht verwendet wird. Dies ist seit der Einführung des Programms in 77ff112 ( read-cache : Cache-Einträge auf Worker-Threads laden, 2018-10-10, Git v2.20.0-rc0).

Nachforschungen in der Mailingliste ergaben, dass dieser Parameter Teil einer eine frühere Ausgabe der Serie Sie wurde jedoch überflüssig, als der Code auf die Verwendung der IEOT-Erweiterung umgestellt wurde.


Mit Git 2.29 (Q4 2020) wird die Formatbeschreibung an die jüngsten SHA-256-Arbeiten angepasst.

Ver Übergabe 8afa50a , 0756e61 festlegen , Commit 123712b , Commit 5b6422a (15. August 2020) von Martin Ågren ( none ) .
(Zusammengefasst von Junio C. Hamano -- gitster -- en Übergabe 74a395c , 19. August 2020)

index-format.txt Dokument: SHA-256-Indexformat

Abgezeichnet von: Martin Ågren

Dokumentieren Sie, dass wir in SHA-1-Repositorien SHA-1 und in SHA-256-Repositorien SHA-256 verwenden, und ersetzen Sie dann alle anderen Verwendungen von "SHA-1" durch etwas Neutraleres.
Vermeiden Sie es, auf "160-Bit"-Hash-Werte zu verweisen.

technical/index-format umfasst nun in seinem Manpage :

Alle Binärzahlen sind in Netzwerk-Byte-Reihenfolge.
In einem Repository, das das traditionelle SHA-1 verwendet, werden Prüfsummen und Objekt-IDs (Objektnamen) alle mit SHA-1 berechnet.
Auch in SHA-256-Repositories werden diese Werte mit SHA-256 berechnet.

Sofern nicht anders angegeben, wird hier die Version 2 beschrieben.

70voto

Bit für Bit-Analyse

Ich habe beschlossen, ein paar Tests durchzuführen, um das Format besser zu verstehen und einige der Felder genauer zu untersuchen.

Die folgenden Ergebnisse sind für alle Git-Versionen gleich 1.8.5.2 y 2.3 .

Ich habe Punkte markiert, bei denen ich mir nicht sicher bin / die ich nicht gefunden habe TODO : Sie können diese Punkte gerne ergänzen.

Wie bereits erwähnt, wird der Index unter .git/index und nicht als Standard-Baumobjekt, und sein 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 denn der Index ist ein Cache für die Erstellung von Übertragungen.

Einrichtung

Wenn wir ein Test-Repository mit starten:

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

El .git Verzeichnis sieht so aus:

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

Und wenn wir den Inhalt des einzigen Objekts erhalten:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Wir erhalten a . Dies zeigt, dass:

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

hd-analyse

Schauen wir uns nun den Index selbst an:

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 abschließ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 die Kopfzeile, definiert unter: struct cache_header :

  • 44 49 52 43 : DIRC . TODO: Warum ist dies notwendig?

  • 00 00 00 02 : Formatversion: 2. Das Indexformat hat sich im Laufe der Zeit weiterentwickelt. Derzeit gibt es Versionen bis zu 4. Das Format des Indexes sollte bei der Zusammenarbeit zwischen verschiedenen Computern auf GitHub kein Problem darstellen, da Bare Repositories den Index nicht speichern: er wird zum Zeitpunkt des Klonens generiert.

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

Als nächstes beginnt eine Liste von Indexeinträgen, die durch struct cache_entry Hier haben wir nur einen. Es enthält:

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

    Beachten Sie, wie:

    • ctime y mtime identisch sind ( 54 09 76 e6 1d 81 6f c6 ) wie erwartet, da wir die Datei nicht geändert haben

      Die ersten Bytes sind die Sekunden seit EPOCH in Hexadezimal:

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

      Gibt:

      Fri Sep  5 10:40:06 CEST 2014

      Deshalb habe ich dieses Beispiel gemacht.

      Die zweiten 4 Bytes sind Nanosekunden.

    • UID und GID sind 00 00 03 e8 1000 in Hexadezimal: ein üblicher Wert für Einzelbenutzer-Einrichtungen.

    All diese Metadaten, von denen die meisten in Baumobjekten nicht vorhanden sind, ermöglichen es Git, schnell zu prüfen, ob eine Datei geändert wurde, ohne den gesamten Inhalt zu vergleichen.

  • am Anfang der Zeile 30 : 00 00 00 02 Dateigröße: 2 Bytes ( a y \n から echo )

  • 78 98 19 22 ... c1 99 4e 85 : 20 Byte SHA-1 über den vorherigen Inhalt des Eintrags. Beachten Sie, dass gemäß meine Experimente mit dem "assume valid"-Flag werden die darauf folgenden Flaggen in diesem SHA-1 nicht berücksichtigt.

  • 2-Byte-Flags: 00 01

    • 1 Bit: gültiges Kennzeichen annehmen. Meine Nachforschungen haben ergeben, dass dieses schlecht benannte Flag der Ort ist, an dem git update-index --assume-unchanged speichert seinen Zustand: https://stackoverflow.com/a/28657085/895245

    • 1 Bit erweitertes Flag. Bestimmt, ob die erweiterten Flaggen vorhanden sind oder nicht. Muss sein 0 bei Version 2, die keine erweiterten Flaggen hat.

    • 2-Bit-Stufenflag, das bei der Zusammenführung verwendet wird. Stadien sind dokumentiert in man git-merge :

      • 0 : reguläre Datei, nicht in einem Merge-Konflikt
      • 1 : Basis
      • 2 : unsere
      • 3 : ihre

      Bei einem Zusammenführungskonflikt werden alle Stufen von 1-3 im Index gespeichert, damit Operationen wie git checkout --ours .

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

    • 12 Bit Länge des folgenden Pfades: 0 01 : Nur 1 Byte, da der Pfad b

  • 2 Byte erweiterte Flaggen. Nur sinnvoll, wenn das "extended flag" bei den Basis-Flags gesetzt wurde. TODO.

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

Dann kommt ein 00 : 1-8 Bytes Null-Padding, 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ß dies, weil in der Datei nicht genügend Platz 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 den Inhalt des Indexes.

12voto

user225312 Punkte 117771

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 übertragen möchten. Wenn Sie eine Übergabe erstellen, wird nur das übergeben, was sich aktuell in diesem Index befindet, nicht das, was sich in Ihrem Arbeitsverzeichnis befindet.

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

git status

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

Sie können lesen este . Eine Google-Suche führt zu zahlreichen Links, die eigentlich ausreichen sollten.

4voto

Saikat Punkte 10782

Der Git-Index ist eine Binärdatei (die im Allgemeinen in .git/index ) mit einer sortierten Liste von Pfadnamen, jeweils mit Berechtigungen und dem SHA1-Wert eines Blob-Objekts;

git ls-files kann Ihnen den Inhalt des Indexes anzeigen. Bitte beachten Sie, dass Wörter index , stage y cache sind in Git dasselbe: Sie werden austauschbar verwendet.

enter image description here

Der Git-Index bzw. Git-Cache hat 3 wichtige Eigenschaften:

  1. Der Index enthält alle notwendigen Informationen, um ein einziges (eindeutig bestimmtes) Baumobjekt zu erzeugen.
  2. Der Index ermöglicht schnelle Vergleiche zwischen dem von ihm definierten Baumobjekt und dem Arbeitsbaum.
  3. Es kann effizient Informationen über Zusammenführungskonflikte zwischen verschiedenen Baumobjekten darstellen, so dass jeder Pfadname mit ausreichenden Informationen über die beteiligten Bäume verknüpft werden kann, so dass Sie eine Drei-Wege-Zusammenführung zwischen ihnen erstellen können.

Fuente :

  1. https://mincong.io/2018/04/28/git-index/
  2. https://medium.com/hackernoon/understanding-git-index-4821a0765cf

2voto

vijayanmr Punkte 11

Als Antwort auf @ciro-santilli-%e9%83%9d%e6%b5%b7%e4%b8%9c%e5%86%a0%e7%8a%b6%e7%97%85%e5%85%ad%e5%9b%9b%e4%ba%8b%e4%bb%b6%e6%b3%95%e8%bd%ae%e5%8a%9f detaillierten Blick auf den Index, teile ich die Ausgabe für eine der TODO .

"Wenn Sie git add verwenden, wird dem Index für den Pfad eine Stufe 0 hinzugefügt, und Git weiß, dass der Konflikt als gelöst markiert wurde. TODO: check this."

Genauer gesagt, die verschiedenen Stufen des Zusammenschlusses.

  • 0: reguläre Datei, nicht in einem Merge-Konflikt
  • 1: Basis
  • 2: unsere
  • 3: ihre

Einzelheiten zur numerischen Darstellung der verschiedenen Phasen, in diesem Fall eine Datei mit Konflikten.

$ git ls-files -s
100644 f72d68f0d10f6efdb8adc8553a1df9c0444a0bec 0       vars/buildComponent.groovy

$ git stash list
stash@{0}: WIP on master: c40172e turn off notifications, temporarily

$ git stash apply
Auto-merging vars/commonUtils.groovy
Auto-merging vars/buildComponent.groovy
CONFLICT (content): Merge conflict in vars/buildComponent.groovy

$ git ls-files -s
100644 bc48727339d36f5d54e14081f8357a0168f4c665 1       vars/buildComponent.groovy
100644 f72d68f0d10f6efdb8adc8553a1df9c0444a0bec 2       vars/buildComponent.groovy
100644 24dd5be1783633bbb049b35fc01e8e88facb20e2 3       vars/buildComponent.groovy

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X