Apa isi indeks git PERSIS?

178

Apa sebenarnya yang terkandung dalam indeks Git, dan perintah apa yang dapat saya gunakan untuk melihat konten indeks?


Memperbarui

Terima kasih atas semua jawaban Anda. Saya tahu bahwa indeks bertindak sebagai area pementasan, dan apa yang dilakukan adalah dalam indeks daripada pohon yang bekerja. Saya hanya ingin tahu tentang apa yang terdiri dari objek indeks. Saya kira itu mungkin daftar nama file / direktori, pasangan SHA-1, semacam pohon virtual mungkin?

Apakah ada, dalam terminologi Git, perintah plumbing yang dapat saya gunakan untuk membuat daftar isi indeks?

mochidino
sumber
3
Anda harus membaca dan menonton diagram - sangat membantu: gitguys.com/topics/whats-the-deal-with-the-git-index
kernix
1
@ernix domain telah kedaluwarsa. Tidak lagi membantu.
narendra-choudhary

Jawaban:

162

Buku Git berisi artikel tentang apa yang termasuk dalam indeks :

Indeks adalah file biner (umumnya disimpan di .git/index) yang berisi daftar nama path yang diurutkan, masing-masing dengan izin dan SHA1 dari objek blob; git ls-filesdapat menunjukkan kepada Anda isi indeks:

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

Masalah Racy git memberikan beberapa detail pada struktur itu:

Indeks adalah salah satu struktur data terpenting dalam git.
Ini mewakili keadaan pohon kerja virtual dengan merekam daftar jalur dan nama objek mereka dan berfungsi sebagai area pementasan untuk menulis objek pohon berikutnya yang akan dikomit.
Statusnya "virtual" dalam arti tidak harus, dan seringkali tidak, cocok dengan file di pohon kerja.


Untuk melihat lebih banyak, lih. " git / git / Dokumentasi / teknis / index-format.txt ":

File indeks Git memiliki format berikut

Semua nomor biner berada dalam urutan byte jaringan.
Versi 2 dijelaskan di sini kecuali dinyatakan sebaliknya.

  • Header 12 byte yang terdiri dari:
    • Tanda tangan 4-byte :
      Tanda tangan adalah {' D', ' I', ' R', ' C'} (singkatan " dircache")
    • Nomor versi 4-byte :
      Versi yang didukung saat ini adalah 2, 3 dan 4.
    • Jumlah entri indeks 32-bit.
  • Sejumlah entri indeks diurutkan .
  • Ekstensi :
    Ekstensi diidentifikasi dengan tanda tangan.
    Ekstensi opsional dapat diabaikan jika Git tidak memahaminya.
    Git saat ini mendukung pohon cache dan menyelesaikan undo ekstensi.
    • Tanda tangan ekstensi 4-byte. Jika byte pertama adalah ' A' .. ' Z' ekstensi bersifat opsional dan dapat diabaikan.
    • Ukuran ekstensi 32-bit
    • Data ekstensi
  • 160-bit SHA-1 atas isi file indeks sebelum checksum ini.

komentar mljrg :

Jika indeks adalah tempat komit selanjutnya disiapkan, mengapa " git ls-files -s" tidak mengembalikan apa pun setelah komit?

Karena indeks mewakili apa yang dilacak , dan tepat setelah komit, apa yang dilacak identik dengan komit terakhir ( git diff --cachedtidak menghasilkan apa-apa).

Jadi git ls-files -sdaftar semua file yang dilacak (nama objek, bit mode dan nomor tahap dalam output).

Daftar tersebut (elemen yang dilacak) diinisialisasi dengan konten komit.
Saat Anda beralih cabang, konten indeks diatur ulang ke komit yang direferensikan oleh cabang yang baru saja Anda alihkan.


Git 2.20 (Q4 2018) menambahkan Tabel Offset Entri Indeks (IEOT) :

Lihat komit 77ff112 , komit 3255089 , komit abb4bb8 , komit c780b9c , komit 3b1d9e0 , komit 371ed0d (10 Okt 2018) oleh Ben Peart ( benpeart) .
Lihat komit 252d079 (26 Sep 2018) oleh Nguyễn Thái Ngọc Duy ( pclouds) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit e27bfaa , 19 Okt 2018)

ieot: tambahkan ekstensi Index Entry Offset Table (IEOT)

Tambalan ini memungkinkan mengatasi biaya CPU dari memuat indeks dengan menambahkan data tambahan ke indeks yang akan memungkinkan kami untuk secara multi-thread memuat dan mengkonversi entri cache.

Ini menyelesaikan ini dengan menambahkan ekstensi indeks (opsional) yang merupakan tabel offset ke blok entri cache dalam file indeks.

Untuk membuat ini bekerja untuk indeks V4, ketika menulis entri cache, secara berkala "me-reset" kompresi awalan dengan menyandikan entri saat ini seolah-olah nama jalur untuk entri sebelumnya benar-benar berbeda dan menyimpan offset entri itu di IEOT .
Pada dasarnya, dengan indeks V4, itu menghasilkan offset menjadi blok entri awalan-terkompresi.

Dengan pengaturan konfigurasi index.threads baru , pemuatan indeks sekarang lebih cepat.


Sebagai hasilnya ( menggunakan IEOT ), komit 7bd9631 membersihkan read-cache.c load_cache_entries_threaded()fungsi untuk Git 2.23 (Q3 2019).

Lihat komit 8373037 , komit d713e88 , komit d92349d , komit 113c29a , komit c95fc72 , komit 7a2a721 , komit c016579 , komit be27fb7 , komit 13a1781 , komit 7bd9631 , komit 3c1dce8 , komit cf7a901 , komit d64db5b , komit 76a7bc0 (9 Mei 2019) oleh Jeff Raja ( peff) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit c0e78f7 , 13 Jun 2019)

read-cache: jatuhkan parameter yang tidak digunakan dari beban berulir

The load_cache_entries_threaded()fungsi mengambil src_offsetparameter yang tidak menggunakan. Ini telah ada sejak awal di 77ff112 ( read-cache: memuat entri cache pada utas pekerja, 2018-10-10, Git v2.20.0-rc0).

Menggali di milis, parameter itu adalah bagian dari iterasi seri sebelumnya , tetapi menjadi tidak perlu ketika kode beralih menggunakan ekstensi IEOT.

VONC
sumber
6
Tentang pentingnya jika indeks dalam model Git, lihat stackoverflow.com/questions/1450348/…
VonC
Tautan pertama di atas menunjuk ke versi git-scm yang tidak memiliki artikel di indeks. Saya pikir maksudnya adalah untuk menunjukkan di sini: schacon.github.io/gitbook/7_the_git_index.html
Kris Giesing
1
@ Krisgiesing Terima kasih atas tautannya. Saya telah memperbarui jawabannya.
VonC
@VonC Jika indeks adalah tempat komit berikutnya disiapkan, mengapa tidak "git ls-files -s" tidak mengembalikan apa pun setelah komit? Pasti ada sesuatu yang lebih tentang indeks daripada yang Anda masukkan dalam jawaban Anda.
mljrg
@mljrg tidak yakin saya mengikuti Anda: setelah komit, tahap (di mana komit sedang disiapkan) akan kosong, karena komit telah dilakukan, bukan?
VonC
62

Analisis sedikit demi sedikit

Saya telah memutuskan untuk melakukan sedikit pengujian untuk lebih memahami format dan meneliti beberapa bidang secara lebih rinci.

Hasil di bawah adalah sama untuk versi Git 1.8.5.2dan 2.3.

Saya telah menandai poin yang saya tidak yakin / belum menemukan TODO: silakan melengkapi poin-poin itu.

Seperti yang disebutkan lain, indeks disimpan di bawah .git/index, bukan sebagai objek pohon standar, dan formatnya adalah biner dan didokumentasikan di: https://github.com/git/git/blob/master/Documentation/technical/index-format. txt

Struct utama yang menentukan indeks adalah pada cache.h , karena indeks adalah cache untuk membuat commit.

Mempersiapkan

Ketika kami memulai repositori pengujian dengan:

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

The .gitdirektori terlihat seperti:

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

Dan jika kita mendapatkan konten dari satu-satunya objek:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Kami mendapatkan a. Ini menunjukkan bahwa:

  • yang indexpoin untuk isi file, karena git add bmenciptakan objek gumpalan
  • ia menyimpan metadata di file indeks, bukan di objek pohon, karena hanya ada satu objek: gumpalan (pada objek Git biasa, gumpalan metadata disimpan di pohon)

analisis hd

Sekarang mari kita lihat indeks itu sendiri:

hd .git/index

Memberi:

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

Selanjutnya kita akan menyimpulkan:

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

Pertama adalah header, didefinisikan di: struct cache_header :

  • 44 49 52 43: DIRC. TODO: mengapa ini perlu?

  • 00 00 00 02: versi format: 2. Format indeks telah berkembang seiring waktu. Saat ini terdapat versi hingga 4. Format indeks seharusnya tidak menjadi masalah ketika berkolaborasi antara komputer yang berbeda di GitHub karena repositori telanjang tidak menyimpan indeks: itu dihasilkan pada waktu klon.

  • 00 00 00 01: jumlah file pada indeks: hanya satu b,.

Selanjutnya mulai daftar entri indeks, ditentukan oleh struct cache_entry Di sini kita hanya punya satu. Itu mengandung:

  • sekelompok metadata file: 8 byte ctime, 8 byte mtime, lalu 4 byte: perangkat, inode, mode, UID dan GID.

    Perhatikan caranya:

    • ctimedan mtimesama ( 54 09 76 e6 1d 81 6f c6) seperti yang diharapkan karena kami belum mengubah file

      Byte pertama adalah detik sejak EPOCH dalam hex:

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

      Memberi:

      Fri Sep  5 10:40:06 CEST 2014
      

      Saat itulah saya membuat contoh ini.

      4 byte kedua adalah nanodetik.

    • UID dan GID adalah 00 00 03 e8, 1000 in hex: nilai umum untuk pengaturan pengguna tunggal.

    Semua metadata ini, yang sebagian besar tidak ada dalam objek pohon, memungkinkan Git untuk memeriksa apakah file telah berubah dengan cepat tanpa membandingkan seluruh konten.

  • di awal baris 30:: 00 00 00 02ukuran file: 2 byte ( adan \ndari echo)

  • 78 98 19 22 ... c1 99 4e 85: 20 byte SHA-1 di atas konten entri sebelumnya. Perhatikan bahwa menurut percobaan saya dengan flag valid , flag yang mengikutinya tidak dipertimbangkan dalam SHA-1 ini.

  • Bendera 2 byte: 00 01

    • 1 bit: anggap bendera yang valid. Investigasi saya menunjukkan bahwa flag dengan nama buruk ini adalah tempat git update-index --assume-unchangedpenyimpanan negaranya: https://stackoverflow.com/a/28657085/895245

    • Bendera diperpanjang 1 bit. Menentukan apakah bendera diperpanjang hadir atau tidak. Harus 0pada versi 2 yang tidak memiliki bendera yang diperluas.

    • Bendera panggung 2 bit digunakan selama penggabungan. Tahapan didokumentasikan dalam man git-merge:

      • 0: file biasa, bukan dalam konflik gabungan
      • 1: base
      • 2: milik kita
      • 3: milik mereka

      Selama konflik penggabungan, semua tahapan dari 1-3 disimpan dalam indeks untuk memungkinkan operasi seperti git checkout --ours.

      Jika Anda git add, maka tahap 0 ditambahkan ke indeks untuk path, dan Git akan tahu bahwa konflik telah ditandai sebagai diselesaikan. TODO: periksa ini.

    • Panjang jalur 12 bit yang akan mengikuti 0 01:: 1 byte hanya sejak jalur itub

  • Bendera diperpanjang 2 byte. Hanya bermakna jika "bendera diperpanjang" ditetapkan pada bendera dasar. MELAKUKAN.

  • 62(ASCII b): jalur panjang variabel. Panjang ditentukan dalam flag sebelumnya, di sini hanya 1 byte b,.

Kemudian muncul sebuah 00: 1-8 byte dari nol padding sehingga path akan diakhiri nol dan indeks akan berakhir dalam kelipatan 8 byte. Ini hanya terjadi sebelum indeks versi 4.

Tidak ada ekstensi yang digunakan. Git tahu ini karena tidak akan ada cukup ruang di file untuk checksum.

Akhirnya ada checksum 20 byte ee 33 c0 3a .. 09 ab 49 94atas isi indeks.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
1
Sangat menarik. +1. Itu menggambarkan jawaban saya sendiri dengan baik. Saya ingin tahu apakah hasil itu akan berubah dengan Git 2.1+ terbaru.
VonC
3
@NielsBom ya, itu akan berhasil juga. Saat menafsirkan program, saya lebih suka mengambil dua pendekatan: pertama empiris untuk melihat apa yang dihasilkannya, dan baru kemudian membaca sumbernya. Kalau tidak, orang mungkin terjebak dalam kasus tepi kode sumber yang bahkan tidak muncul pada output sederhana. Tentu saja, saya memang melihat source struct untuk membantu membimbing saya, dan setiap TODO dapat menyelesaikan bacaan saya bagaimana struct tersebut dimanipulasi, yang merupakan bagian yang sulit.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@CiroSantilli 六四 事件 法轮功 纳米比亚 威 视: Jika saya memodifikasi indeks dalam hex editor dan memperbarui checksum 20 byte, apakah ada perintah untuk memperbarui sha1 yang disimpan di objek lain? (git mengeluh kalau tanda tangan indeks rusak) . Juga data indeks disimpan dengan cara yang sama sekali berbeda ketika dikirim melalui permintaan push.
user2284570
1
@CiroSantilli 六四 事件 法轮功 纳米比亚 威 视: Tujuan keamanan. Hanya mencari jenis yang dikenal baik serangan file gambar raster diterapkan ke git database / objek. (tentu saja saya tahu sebagian besar implementasi baru-baru ini menangani perspektif itu, tapi mungkin tidak semua)  Jadi saya terutama mencari struktur data biner yang memberitahu panjang array. (mengenai buffer teks, tampaknya penghentian nol adalah norma untuk memberi tahu jumlah baris)
user2284570
1
Mengenai git add, per Anda TODO: Anda benar. Jika Anda memiliki entri indeks tahap tinggi (konflik) di jalur yang diberikan, saat Anda git addjalur itu, semua entri indeks tahap tinggi akan dihapus dan salinan direktori kerja akan ditambahkan pada tahap 0. (Menyelesaikan konflik).
Edward Thomson
11

Indeks Git adalah area pementasan antara direktori kerja Anda dan repositori Anda. Anda dapat menggunakan indeks untuk membangun satu set perubahan yang ingin Anda lakukan bersama. Saat Anda membuat komit, apa yang dikomit adalah apa yang saat ini ada di indeks ini, bukan apa yang ada di direktori kerja Anda.

Untuk melihat apa yang ada di dalam indeks, berikan perintah:

git status

Ketika Anda menjalankan status git, Anda dapat melihat file mana yang dipentaskan (saat ini dalam indeks Anda), yang dimodifikasi tetapi belum dipentaskan, dan mana yang sepenuhnya tidak terlacak.

Anda bisa membaca ini . Pencarian Google memunculkan banyak tautan, yang seharusnya cukup mandiri.

pengguna225312
sumber
7
git statustidak mencantumkan semua file dari indeks. Hanya daftar file-file yang berbeda antara indeks dan direktori kerja. Untuk melihat semua file dalam indeks, Anda perlu menggunakan git ls-files.
Akash Agrawal
1
@AkashAgrawal, git status memang daftar file indeks, terlepas dari apakah mereka berbeda antara indeks dan workdir.
Acumenus
3
ya, itu daftar BEBERAPA file indeks, tetapi tidak menunjukkan semua yang ada di dalam indeks, yang adalah apa yang dikatakan dalam jawabannya. Itu seperti mengatakan ada 2 bola hijau dan 3 bola merah di dalam kotak. Untuk melihat apa yang ada di dalam kotak, tarik keluar 2 bola hijau. Apa yang Akash katakan paling akurat, untuk melihat semua file dalam indeks, gunakan git ls-file.
dave4jr
3
Memang. git statusdaftar file yang ada dalam indeks, ya, tetapi tidak mencantumkan semua file dalam indeks. Menjelaskan bagaimana git status sebenarnya bekerja akan menjadi jawaban yang bermanfaat untuk beberapa pertanyaan, meskipun mungkin bukan yang ini.
Edward Thomson
1
git statusmenunjukkan status pohon kerja (perbedaan antara pohon kerja dan indeks). Sebenarnya tidak menunjukkan indeks. git-scm.com/docs/git-status
wisbucky
1

Inilah yang sebenarnya Anda butuhkan, gunakan perintah ini.

$ 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
lh
sumber
0

Git index adalah file biner (umumnya disimpan .git/index) yang berisi daftar nama path yang diurutkan, masing-masing dengan izin dan SHA1 dari objek blob;

git ls-filesdapat menunjukkan kepada Anda isi indeks. Harap perhatikan bahwa kata-kata index,, stagedan cachehal yang sama di Git: digunakan secara bergantian.

masukkan deskripsi gambar di sini

Indeks Git, atau Git cache, memiliki 3 properti penting:

  1. Indeks berisi semua informasi yang diperlukan untuk menghasilkan objek pohon tunggal (ditentukan secara unik).
  2. Indeks memungkinkan perbandingan cepat antara objek pohon yang ditentukannya dan pohon kerja.
  3. Ini dapat secara efisien merepresentasikan informasi tentang menggabungkan konflik antara objek pohon yang berbeda, memungkinkan setiap nama jalur untuk dikaitkan dengan informasi yang cukup tentang pohon yang terlibat sehingga Anda dapat membuat gabungan tiga arah di antara mereka.

Sumber :

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