Git endeksi TAM NEDİR içerir?


178

Git dizini tam olarak ne içeriyor ve dizinin içeriğini görüntülemek için hangi komutu kullanabilirim?


Güncelleme

Tüm cevaplarınız için teşekkürler. Endeksin bir evreleme alanı olduğunu ve işlenen şeyin çalışma ağacı yerine dizinde olduğunu biliyorum. Sadece bir dizin nesnesinin nelerden oluştuğunu merak ediyorum. Sanırım dosya adı / dizin adı, SHA-1 çiftleri, belki de bir çeşit sanal ağaç olabilir?

Git terminolojisinde, dizinin içeriğini listelemek için kullanabileceğim herhangi bir tesisat komutu var mı?



3
şemaları okumalı ve izlemelisiniz - çok yararlı: gitguys.com/topics/whats-the-deal-with-the-git-index
kernix 4:13

1
@ alan adının süresi doldu. Artık çok yararlı değil.
narendra-choudhary

Yanıtlar:


162

Git kitabı bir dizinin içeriğine dair bir makale içerir :

Dizin .git/index, her biri izinlere ve bir blob nesnesinin SHA1'e sahip sıralı yol adları listesini içeren bir ikili dosyadır (genellikle tutulur ); git ls-filessize dizinin içeriğini gösterebilir:

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

Açık saçık git sorun o yapı üzerinde biraz daha ayrıntı verir:

Dizin git'teki en önemli veri yapılarından biridir.
Yolların listesini ve nesne adlarını kaydederek sanal bir çalışma ağacı durumunu temsil eder ve işlenecek bir sonraki ağaç nesnesini yazmak için bir hazırlama alanı görevi görür.
Durum, çalışma ağacındaki dosyaları zorunlu olarak eşleştirmek zorunda olmadığı ve çoğu zaman eşleşmediği anlamında "sanal" dır.


Daha fazlasını görmek için bkz. " git / git / Dokümantasyon / teknik / index-format.txt ":

Git dizin dosyası aşağıdaki biçime sahiptir

Tüm ikili sayılar ağ bayt sırasına göre verilmiştir.
Sürüm 2 , aksi belirtilmedikçe burada açıklanmaktadır.

  • Aşağıdakilerden oluşan 12 baytlık bir başlık:
    • 4 baytlık imza :
      İmza {' D', ' I', ' R', ' C'} (" dircache" anlamına gelir )
    • 4 bayt sürüm numarası :
      Desteklenen geçerli sürümler 2, 3 ve 4'tür.
    • 32 bit dizin girişi sayısı.
  • Bir dizi sıralı dizin girişi .
  • Uzantılar :
    Uzantılar imza ile tanımlanır.
    Git bunları anlamadığında isteğe bağlı uzantılar yok sayılabilir.
    Git şu anda önbelleğe alınmış ağacı destekler ve geri alma uzantılarını çözer.
    • 4 bayt uzantı imzası. İlk bayt ' A' .. ' Z' ise uzantı isteğe bağlıdır ve yok sayılabilir.
    • Uzantının 32 bit boyutu
    • Uzantı verileri
  • Bu sağlama toplamından önce dizin dosyasının içeriği üzerinde 160 bit SHA-1.

mljrg yorumlar :

Endeks bir sonraki taahhüdün hazırlandığı yerse, " git ls-files -s" işlemden sonra neden hiçbir şey döndürmüyor?

Endeks, izlenmekte olanı temsil ettiğinden ve bir taahhütten hemen sonra, izlenmekte olan git diff --cachedşey son taahhütle özdeştir ( hiçbir şey döndürmez).

Böylece git ls-files -sizlenen tüm dosyaları listeler (çıktıdaki nesne adı, mod bitleri ve sahne numarası).

Bu liste (izlenen öğenin) bir taahhüdün içeriği ile başlatılır.
Şubeyi değiştirdiğinizde, dizin içeriği, az önce geçiş yaptığınız dalın başvurduğu kesinliğe sıfırlanır.


Git 2.20 (4. Çeyrek 2018) bir Endeks Giriş Ofseti Tablosu (IEOT) ekliyor :

Bkz. Taahhüt 77ff112 , taahhüt 3255089 , taahhüt abb4bb8 , taahhüt c780b9c , taahhüt 3b1d9e0 , taahhüt 371ed0d (10 Ekim 2018), Ben Peart ( benpeart) .
Bakınız Nguy2n Thái Ngọc Duy ( pclouds) tarafından 252d079 (26 Eyl 2018) taahhüdü .
(Tarafından Birleştirilmiş Junio C Hamano - gitster- içinde taahhüt e27bfaa , 19 Ekim 2018)

ieot: Dizin Giriş Ofseti Tablosu (IEOT) uzantısı ekle

Bu düzeltme eki, dizine önbellek girdilerinin yüklenmesini ve dönüştürülmesini verimli bir şekilde çok işleyebilmemizi sağlayacak ek veriler ekleyerek dizinin yüklenmesinin CPU maliyetinin ele alınmasını sağlar.

Bunu, dizin dosyasındaki önbellek girdileri bloklarına ofsetler tablosu olan (isteğe bağlı) bir dizin uzantısı ekleyerek gerçekleştirir.

V4 dizinleri için bu işi yapmak için, önbellek girdilerini yazarken, önceki girdinin yol adı tamamen farklıymış gibi geçerli girdiyi kodlayarak önek sıkıştırmasını periyodik olarak "sıfırlar" ve IEOT'taki girdinin ofsetini kaydeder .
Temel olarak, V4 indeksleri ile önek sıkıştırılmış giriş bloklarına ofsetler üretir.

İle yeni index.threads yapılandırma ayarı , endeks yükleme artık daha hızlı.


Sonuç olarak ( IEOT kullanarak ), Git 2.23 (Q3 2019) işlevini 7bd9631 temizleme read-cache.c load_cache_entries_threaded()işlevini tamamlayın .

Bkz 8373037 işlemek , d713e88 işlemek , d92349d işlemek , 113c29a işlemek , işlemek c95fc72 , 7a2a721 taahhüt , c016579 işlemek , işlemek be27fb7 , 13a1781 taahhüt , 7bd9631 taahhüt , 3c1dce8 taahhüt , cf7a901 işlemek , d64db5b işlemek , 76a7bc0 taahhüt tarafından (2019 09 Mayıs) Jeff Kral ( peff) .
(Göre Birleştirilmiş Junio Cı Hamano - gitster- içinde işlemek c0e78f7 , 13 Haziran 2019)

read-cache: kullanılmayan parametreyi dişli yükten çıkar

load_cache_entries_threaded()Fonksiyon alır src_offseto kullanmayan parametreyi. Bu, 77ff112'deki başlangıcından beri var ( read-cache: çalışan iş parçacıklarına yük önbellek girdileri, 2018-10-10, Git v2.20.0-rc0).

Posta listesinde kazıldığında , bu parametre serinin daha önceki bir yinelemesinin bir parçasıydı , ancak kod IEOT uzantısını kullanmaya geçtiğinde gereksiz hale geldi.


6
Git modelindeki dizinin önemi hakkında bilgi için bkz. Stackoverflow.com/questions/1450348/…
VonC

Yukarıdaki ilk bağlantı, dizinde makale olmayan bir git-scm sürümünü gösterir. Bence niyet burada işaret etmekti
Kris Giesing

1
@KrisGiesing Bağlantı için teşekkürler. Cevabı güncelledim.
VonC

@VonC Dizin bir sonraki taahhüdün hazırlandığı yerdirsa, neden "git ls-files -s" işlemden sonra hiçbir şey döndürmez? Dizin hakkında, cevabınıza koyduğunuzdan daha fazla bir şey olmalı.
mljrg

@mljrg sizi takip ettiğimden emin değilim: bir taahhütten sonra , taahhüt tamamlandıktan sonra sahne (taahhüdün hazırlandığı yer) boş olurdu, değil mi?
VonC

62

Bit-bit analizi

Biçimi daha iyi anlamak ve bazı alanları daha ayrıntılı olarak araştırmak için küçük bir test yapmaya karar verdim.

Aşağıdaki sonuçlar Git sürümleri 1.8.5.2ve için aynıdır 2.3.

Emin olmadığım / bulamadığım puanları işaretledim TODO: lütfen bu noktaları tamamlamaktan çekinmeyin.

Diğerleri de belirtildiği gibi, dizin .git/indexstandart bir ağaç nesnesi olarak değil altında saklanır ve biçimi ikiliktir ve https://github.com/git/git/blob/master/Documentation/technical/index-format adresinde belgelenir . Txt

Dizini tanımlayan ana yapılar cache.h dizinindedir , çünkü dizin taahhütleri oluşturmak için bir önbellektir.

Kurmak

Aşağıdakilerle bir test deposu başlattığımızda:

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

.gitDizin görünüyor gibi:

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

Ve tek nesnenin içeriğini alırsak:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Anlıyoruz a. Bu şunu gösterir:

  • indexDosya içeriğine puan, çünkü git add bbir damla nesnesini oluşturan
  • yalnızca tek bir nesne bulunduğundan meta verileri dizin dosyasında saklar, nesne içinde saklar: blob (normal Git nesnelerinde, blob meta verileri ağaçta depolanır)

hd analizi

Şimdi dizinin kendisine bakalım:

hd .git/index

verir:

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

Sonra şu sonuca varacağız:

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

İlk önce şu başlıkta tanımlanan başlık gelir: struct cache_header :

  • 44 49 52 43: DIRC. YAPILACAKLAR: Bu neden gerekli?

  • 00 00 00 02: biçim sürümü: 2. Dizin biçimi zamanla gelişmiştir. Şu anda 4'e kadar sürüm var. GitHub'daki farklı bilgisayarlar arasında işbirliği yapılırken dizinin biçimi bir sorun olmamalı çünkü çıplak depolar dizini saklamıyor: klon zamanında üretiliyor.

  • 00 00 00 01: dizindeki dosya sayısı: sadece bir b,.

Sonra cache_entry struct tarafından tanımlanan dizin girişlerinin bir listesini başlatır Burada sadece bir tane var. Bu içerir:

  • bir grup dosya meta verisi: 8 bayt ctime, 8 bayt mtime, sonra 4 bayt: cihaz, inode, mod, UID ve GID.

    Nasıl yapıldığına dikkat edin:

    • ctimeve dosyayı değiştirmediğimizden beklenenle mtimeaynı ( 54 09 76 e6 1d 81 6f c6)

      İlk bayt, onaltılık EPOCH değerinden bu yana geçen saniyedir:

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

      verir:

      Fri Sep  5 10:40:06 CEST 2014
      

      İşte o zaman bu örneği yaptım.

      İkinci 4 bayt nanosaniyedir.

    • UID ve GID, 00 00 03 e8hex cinsinden 1000'dir: tek kullanıcılı kurulumlar için ortak bir değerdir.

    Çoğu ağaç nesnelerinde bulunmayan bu meta verilerin tümü Git'in bir dosyanın tüm içeriği karşılaştırmadan hızlı bir şekilde değişip değişmediğini kontrol etmesini sağlar.

  • satırın başında 30: 00 00 00 02: Dosya boyutu: 2 byte ( ave \ngelen echo)

  • 78 98 19 22 ... c1 99 4e 85: Girdinin önceki içeriğine göre 20 bayt SHA-1. Geçerli bayrak varsayımıyla yaptığım deneylere göre , onu takip eden bayrakların bu SHA-1'de dikkate alınmadığını unutmayın.

  • 2 bayt bayrağı: 00 01

    • 1 bit: geçerli bayrağı kabul edin. Araştırmalarım, bu kötü adlandırılmış bayrağın git update-index --assume-unchangeddurumunu depoladığı yer olduğunu gösteriyor : https://stackoverflow.com/a/28657085/895245

    • 1 bit genişletilmiş bayrak. Genişletilmiş bayrakların olup olmadığını belirler. 0Genişletilmiş bayrakları olmayan sürüm 2'de olmalıdır .

    • Birleştirme sırasında kullanılan 2 bit sahne bayrağı. Aşamalar belgelenmiştir man git-merge:

      • 0: birleştirme çakışmasında olmayan normal dosya
      • 1: baz
      • 2: bizimki
      • 3: onların

      Birleştirme çakışması sırasında, 1-3'ten sonraki tüm aşamalar gibi işlemlere izin vermek için dizinde depolanır git checkout --ours.

      Siz yaparsanız git add, yolun dizinine bir aşama 0 eklenir ve Git çakışmanın çözülmüş olarak işaretlendiğini bilir. YAPILACAKLAR: Bunu kontrol et.

    • İzlenecek yolun 12 bit uzunluğu 0 01:: yalnızca yol olduğu için 1 baytb

  • 2 bayt genişletilmiş bayraklar. Sadece "genişletilmiş bayrak" temel bayraklarda ayarlanmışsa anlamlıdır. YAPMAK.

  • 62(ASCII b): değişken uzunluk yolu. Önceki bayraklarda belirlenen uzunluk, burada sadece 1 bayt b.

Sonra a 00: 1-8 bayt sıfır dolgusu gelir, böylece yol null sonlandırılır ve dizin 8 baytın katıyla biter. Bu yalnızca dizin sürüm 4'ten önce olur.

Hiçbir uzantı kullanılmadı. Git bunu bilir, çünkü dosyada sağlama toplamı için yeterli alan kalmaz.

Son olarak ee 33 c0 3a .. 09 ab 49 94, dizinin içeriği üzerinde 20 baytlık bir sağlama toplamı vardır .


1
Çok ilginç. +1. Bu benim kendi cevabımı güzel bir şekilde gösteriyor. Bu sonuçların en son Git 2.1+ ile değişip değişmeyeceğini merak ediyorum.
VonC

3
@NielsBom evet, bu da işe yarar. Programları yorumlarken, iki yaklaşım benimsemeyi tercih ederim: ilk önce hangi çıktıları ürettiğini görmek için ampirik, ancak daha sonra kaynağı okuyun. Aksi takdirde, basit çıktılarda bile görünmeyen kaynak kodu kenar durumlarına takılabilir. Tabii ki, bana rehberlik etmek için kaynak yapılara baktım ve her TODO, bu yapıların nasıl manipüle edildiğini okumamı çözebilir, bu da zor kısımdır.
Ciro Santilli 法轮功 13 病 六四 事件 法轮功

1
@CiroSantilli 视 事件 法轮功 纳米比亚 威 视: Dizini onaltılık düzenleyicide değiştirir ve 20 bayt sağlama toplamını güncelleştirirsem, diğer nesnelerde depolanan sha1'i güncelleme komutu var mı? (git, dizinin sha1 imzasının bozuk olduğundan şikayet eder) . Ayrıca indeks verileri, push istekleri üzerine gönderildiğinde tamamen farklı bir şekilde saklanır.
user2284570

1
@CiroSantilli 视 事件 法轮功 纳米比亚 威 视: Güvenlik amaçları. Sadece git veritabanı / nesnelere uygulanan raster görüntü dosyaları saldırıları iyi bilmek tür arıyor. (Tabii ki çoğu uygulama son zamanlarda bu perspektif, ama muhtemelen hepsi hallettim biliyorum)  Bu yüzden özellikle bir dizi uzunluğunu söyleyen ikili veri yapıları arıyorum. (metin arabellekleri ile ilgili olarak boş sonlandırma satır sayısını
belirtme normudur

1
İlgili git add, başına senin TODO: Eğer doğru. Belirli bir yolda yüksek aşamalı dizin girişleriniz (çakışma) varsa, git addbu yolu kullandığınızda tüm yüksek aşamalı dizin girişleri kaldırılır ve çalışma dizini kopyası aşamada eklenir 0. (Çatışmanın çözümü).
Edward Thomson

11

Git dizini, çalışma dizininiz ve deponuz arasındaki bir hazırlama alanıdır. Dizini, birlikte işlemek istediğiniz bir dizi değişiklik oluşturmak için kullanabilirsiniz. Bir taahhüt oluşturduğunuzda, taahhüt edilen şey, çalışma dizininizde değil, şu anda bu dizinde olan şeydir.

Dizinin içinde ne olduğunu görmek için şu komutu verin:

git status

Git durumunu çalıştırdığınızda, hangi dosyaların değiştirildiğini (şu anda dizininizde), hangilerinin değiştirildiğini ancak henüz sahnelenmediğini ve hangilerinin tamamen izlenmediğini görebilirsiniz.

Okuyabiliyorsun bu . Google araması, kendi kendine yeterli olması gereken birçok bağlantı atar.


7
git statusdizindeki tüm dosyaları listelemez. Yalnızca dizin ve çalışma dizini arasında farklılık gösteren dosyaları listeler. Dizindeki tüm dosyaları görmek için kullanmanız gerekir git ls-files.
Akash Agrawal

1
@AkashAgrawal, git status does bakılmaksızın indeksi ve WORKDIR arasında farklılık olup olmadığı, gerçeği listesi indeks dosyaları.
Acumenus

3
evet, BAZI dizin dosyalarını listeler, ancak size dizin içindeki her şeyi göstermez, bu da cevabındaki ifadesinin söylediği şeydir. Bu, bir kutunun içinde 2 yeşil top ve 3 kırmızı top olduğunu söylemek gibidir. Kutunun içinde ne olduğunu görmek için 2 yeşil topu dışarı çekin. Akash'ın söyledikleri en doğrudur, dizindeki tüm dosyaları görmek için git ls-files kullanın.
dave4jr

3
Aslında. git statusdizindeki dosyaları listeler, evet, ancak dizindeki tüm dosyaları listelemez . git status Gerçekten nasıl çalıştığını açıklamak , muhtemelen bu olmasa da, bazı sorulara faydalı bir cevap olacaktır.
Edward Thomson

1
git statusçalışma ağacı durumunu gösterir (çalışma ağacı ve dizin arasındaki fark). Aslında dizini göstermez. git-scm.com/docs/git-status
wisbucky

1

İşte tam olarak ihtiyacınız olan şey bu komutu kullanın.

$ 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 dizini .git/index, her biri izinlere ve bir blob nesnesinin SHA1'e sahip sıralı yol adları listesini içeren ikili bir dosyadır (genellikle tutulur );

git ls-filessize dizinin içeriğini gösterebilir. Kelimeleri böyle unutmayınız index, stageve cacheGit aynı şeyi ifade eder birbirinin yerine kullanılır.

resim açıklamasını buraya girin

Git dizini veya Git önbelleğinin 3 önemli özelliği vardır:

  1. Dizin, tek (benzersiz olarak belirlenmiş) bir ağaç nesnesi oluşturmak için gerekli tüm bilgileri içerir.
  2. Dizin, tanımladığı ağaç nesnesi ile çalışma ağacı arasında hızlı karşılaştırmalar yapılmasını sağlar.
  3. Farklı ağaç nesneleri arasındaki birleştirme çakışmaları hakkındaki bilgileri etkin bir şekilde temsil edebilir, böylece her yol adının ilgili ağaçlar hakkında yeterli bilgi ile ilişkilendirilmesine izin vererek aralarında üç yönlü birleştirme oluşturabilirsiniz.

Kaynak :

  1. https://mincong.io/2018/04/28/git-index/
  2. https://medium.com/hackernoon/understanding-git-index-4821a0765cf
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.