Chỉ số git chứa chính xác là gì?


177

Chỉ mục Git chứa chính xác những gì và tôi có thể sử dụng lệnh nào để xem nội dung của chỉ mục?


Cập nhật

Cảm ơn tất cả các câu trả lời của bạn. Tôi biết rằng chỉ mục hoạt động như một khu vực tổ chức, và những gì được cam kết là trong chỉ mục chứ không phải là cây làm việc. Tôi chỉ tò mò về những gì một đối tượng chỉ số bao gồm. Tôi đoán nó có thể là một danh sách tên tệp / tên thư mục, cặp SHA-1, một loại cây ảo có thể?

Có, trong thuật ngữ Git, bất kỳ lệnh hệ thống ống nước nào tôi có thể sử dụng để liệt kê các nội dung của chỉ mục?



3
bạn nên đọc và xem sơ đồ - rất hữu ích: gitguys.com/topics/whats-the-deal-with-the-git-index
kernix

1
@kernix tên miền đã hết hạn. Không còn hữu ích nữa.
narendra-choudhary

Câu trả lời:


162

Cuốn sách Git chứa một bài viết về những gì một chỉ mục bao gồm :

Chỉ mục là một tệp nhị phân (thường được lưu giữ .git/index) chứa danh sách tên đường dẫn được sắp xếp, mỗi tên có quyền và SHA1 của đối tượng blob; git ls-filescó thể cho bạn thấy nội dung của chỉ mục:

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

Các vấn đề Admin git cho một số chi tiết về cấu trúc:

Chỉ mục là một trong những cấu trúc dữ liệu quan trọng nhất trong git.
Nó đại diện cho trạng thái cây làm việc ảo bằng cách ghi lại danh sách các đường dẫn và tên đối tượng của chúng và đóng vai trò là khu vực tổ chức để viết ra đối tượng cây tiếp theo được cam kết.
Trạng thái là "ảo" theo nghĩa là nó không nhất thiết phải và thường không khớp với các tệp trong cây làm việc.


Để xem thêm, hãy xem " git / git / Tài liệu / kỹ thuật / index-format.txt ":

Tệp chỉ mục Git có định dạng sau

Tất cả các số nhị phân theo thứ tự byte mạng.
Phiên bản 2 được mô tả ở đây trừ khi có quy định khác.

  • Một tiêu đề 12 byte bao gồm:
    • Chữ ký 4 byte :
      Chữ ký là {' D', ' I', ' R', ' C'} (viết tắt của " dircache")
    • Số phiên bản 4 byte :
      Các phiên bản được hỗ trợ hiện tại là 2, 3 và 4.
    • Số lượng mục nhập 32 bit.
  • Một số mục chỉ mục được sắp xếp .
  • Phần mở rộng :
    Phần mở rộng được xác định bằng chữ ký.
    Các tiện ích mở rộng tùy chọn có thể bị bỏ qua nếu Git không hiểu chúng.
    Git hiện hỗ trợ cây được lưu trữ và giải quyết các phần mở rộng.
    • Chữ ký mở rộng 4 byte. Nếu byte đầu tiên là ' A' .. ' Z' thì phần mở rộng là tùy chọn và có thể bỏ qua.
    • Kích thước 32 bit của phần mở rộng
    • Dữ liệu mở rộng
  • SHA-1 160 bit so với nội dung của tệp chỉ mục trước tổng kiểm tra này.

ý kiến mljrg :

Nếu chỉ mục là nơi chuẩn bị cam kết tiếp theo, tại sao " git ls-files -s" không trả lại gì sau khi cam kết?

Bởi vì chỉ mục đại diện cho những gì đang được theo dõi và ngay sau một cam kết, những gì đang được theo dõi giống hệt với cam kết cuối cùng ( git diff --cachedkhông trả về gì).

Vì vậy, git ls-files -sliệt kê tất cả các tệp được theo dõi (tên đối tượng, bit chế độ và số giai đoạn trong đầu ra).

Danh sách đó (của phần tử được theo dõi) được khởi tạo với nội dung của một cam kết.
Khi bạn chuyển nhánh, nội dung chỉ mục được đặt lại thành cam kết được tham chiếu bởi nhánh bạn vừa chuyển sang.


Git 2.20 (Q4 2018) thêm Bảng bù cho mục nhập chỉ mục (IEOT) :

Xem cam kết 77ff112 , cam kết 3255089 , cam kết abb4bb8 , cam kết c780b9c , cam kết 3b1d9e0 , cam kết 371ed0d (ngày 10 tháng 10 năm 2018) của Ben Peart ( benpeart) .
Xem cam kết 252d079 (ngày 26 tháng 9 năm 2018) của Nguyễn Thái Ngọc Duy ( pclouds) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết e27bfaa , ngày 19 tháng 10 năm 2018)

egot: thêm phần mở rộng Index Offset Table (IEOT)

Bản vá này cho phép giải quyết chi phí CPU khi tải chỉ mục bằng cách thêm dữ liệu bổ sung vào chỉ mục sẽ cho phép chúng tôi đa luồng hiệu quả việc tải và chuyển đổi các mục trong bộ đệm.

Nó thực hiện điều này bằng cách thêm một phần mở rộng chỉ mục (tùy chọn) là một bảng bù cho các khối mục nhập bộ đệm trong tệp chỉ mục.

Để làm việc này cho các chỉ mục V4, khi viết các mục trong bộ đệm, nó định kỳ "đặt lại" nén tiền tố bằng cách mã hóa mục nhập hiện tại như thể tên đường dẫn cho mục trước đó hoàn toàn khác nhau và lưu phần bù của mục đó trong IEOT .
Về cơ bản, với các chỉ mục V4, nó tạo ra các độ lệch thành các khối của các mục được nén tiền tố.

Với cài đặt cấu hình index.threads mới , việc tải chỉ mục giờ đây nhanh hơn.


Kết quả là ( sử dụng IEOT ), cam kết 7bd9631 dọn sạch read-cache.c load_cache_entries_threaded()chức năng cho Git 2.23 (quý 3 năm 2019).

Xem cam 8373037 , cam kết d713e88 , cam kết d92349d , cam kết 113c29a , cam kết c95fc72 , cam kết 7a2a721 , cam kết c016579 , cam kết be27fb7 , cam kết 13a1781 , cam kết 7bd9631 , cam kết 3c1dce8 , cam kết cf7a901 , cam kết d64db5b , cam kết 76a7bc0 (ngày 09 tháng 5 năm 2019) bởi Jeff Vua ( peff) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết c0e78f7 , ngày 13 tháng 6 năm 2019)

read-cache: thả tham số không sử dụng khỏi tải luồng

Các load_cache_entries_threaded()chức năng phải mất một src_offsettham số mà nó không sử dụng. Điều này đã có từ khi nó ra đời vào năm 77ff112 ( read-cache: tải các mục bộ đệm trong các luồng công nhân, 2018-10-10, Git v2.20.0-rc0).

Đi sâu vào danh sách gửi thư, tham số đó là một phần của lần lặp trước của chuỗi , nhưng trở nên không cần thiết khi mã chuyển sang sử dụng phần mở rộng IEOT.


6
Về tầm quan trọng nếu chỉ mục trong mô hình Git, hãy xem stackoverflow.com/questions/1450348/iêu
VonC

Liên kết đầu tiên ở trên chỉ ra một phiên bản của git-scm không có bài viết về chỉ mục. Tôi nghĩ ý định đã chỉ ra ở đây: schacon.github.io/gitbook/7_the_git_index.html
Kris Giesing

1
@KrisGiesing Cảm ơn bạn đã liên kết. Tôi đã cập nhật câu trả lời.
VonC

@VonC Nếu chỉ mục là nơi chuẩn bị cam kết tiếp theo, tại sao "git ls-files -s" không trả về gì sau khi xác nhận? Phải có một cái gì đó nhiều hơn về chỉ số hơn bạn đã đưa vào câu trả lời của bạn.
mljrg

@mljrg không chắc chắn tôi theo bạn: sau khi cam kết, giai đoạn (nơi cam kết đã được chuẩn bị) sẽ trống, vì cam kết đã được thực hiện, phải không?
VonC

62

Phân tích từng bit

Tôi đã quyết định thực hiện một thử nghiệm nhỏ để hiểu rõ hơn về định dạng và nghiên cứu một số lĩnh vực chi tiết hơn.

Kết quả dưới đây là giống nhau cho các phiên bản Git 1.8.5.22.3.

Tôi đã đánh dấu những điểm mà tôi không chắc chắn / chưa tìm thấy TODO: xin vui lòng bổ sung những điểm đó.

Như những người khác đã đề cập, chỉ mục được lưu trữ bên dưới .git/index, không phải là một đối tượng cây tiêu chuẩn và định dạng của nó là nhị phân và được ghi lại tại: https://github.com/git/git/blob/master/Documentation/technical/index-format. txt

Các cấu trúc chính xác định chỉ mục là tại cache.h , vì chỉ mục là bộ đệm để tạo các xác nhận.

Thiết lập

Khi chúng tôi bắt đầu một kho lưu trữ thử nghiệm với:

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

Thư mục .gittrông giống như:

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

Và nếu chúng ta có được nội dung của đối tượng duy nhất:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Chúng tôi nhận được a. Điều này chỉ ra rằng:

  • các indexđiểm đến nội dung tập tin, kể từ khi git add btạo một đối tượng blob
  • nó lưu trữ siêu dữ liệu trong tệp chỉ mục, không phải trong một đối tượng cây, vì chỉ có một đối tượng duy nhất: blob (trên các đối tượng Git thông thường, siêu dữ liệu blob được lưu trữ trên cây)

phân tích hd

Bây giờ hãy xem xét chính chỉ số:

hd .git/index

Cung cấp:

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

Tiếp theo chúng tôi sẽ kết luận:

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

Đầu tiên là tiêu đề, được định nghĩa tại: struct cache_header :

  • 44 49 52 43: DIRC. TODO: tại sao điều này lại cần thiết?

  • 00 00 00 02: định dạng phiên bản: 2. Định dạng chỉ mục đã phát triển theo thời gian. Hiện tại có phiên bản tồn tại lên đến 4. Định dạng của chỉ mục không phải là vấn đề khi cộng tác giữa các máy tính khác nhau trên GitHub vì kho lưu trữ trần không lưu trữ chỉ mục: nó được tạo tại thời điểm sao chép.

  • 00 00 00 01: số lượng tệp trên chỉ mục: chỉ một , b.

Tiếp theo bắt đầu một danh sách các mục chỉ mục, được xác định bởi struct cache_entry Ở đây chúng tôi chỉ có một. Nó chứa:

  • một loạt siêu dữ liệu tệp: 8 byte ctime, 8 byte mtime, sau đó 4 byte: thiết bị, inode, chế độ, UID và GID.

    Lưu ý cách làm:

    • ctimemtimegiống ( 54 09 76 e6 1d 81 6f c6như mong đợi vì chúng tôi chưa sửa đổi tệp

      Các byte đầu tiên là giây kể từ EPOCH ở dạng hex:

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

      Cung cấp:

      Fri Sep  5 10:40:06 CEST 2014
      

      Đó là khi tôi làm ví dụ này.

      4 byte thứ hai là nano giây.

    • UID và GID là 00 00 03 e81000 in hex: một giá trị chung cho các thiết lập người dùng.

    Tất cả các siêu dữ liệu này, hầu hết không có trong các đối tượng cây, cho phép Git kiểm tra xem một tệp có thay đổi nhanh chóng hay không mà không so sánh toàn bộ nội dung.

  • ở đầu dòng 30:: 00 00 00 02kích thước tệp: 2 byte ( a\ntừ echo)

  • 78 98 19 22 ... c1 99 4e 85: 20 byte SHA-1 so với nội dung trước đó của mục nhập. Lưu ý rằng theo các thử nghiệm của tôi với cờ hợp lệ giả định , các cờ tuân theo nó không được xem xét trong SHA-1 này.

  • Cờ 2 byte: 00 01

    • 1 bit: giả sử cờ hợp lệ. Các cuộc điều tra của tôi chỉ ra rằng lá cờ được đặt tên kém này là nơi git update-index --assume-unchangedlưu trữ trạng thái của nó: https://stackoverflow.com/a/28657085/895245

    • Cờ mở rộng 1 bit. Xác định xem các cờ mở rộng có mặt hay không. Phải 0ở phiên bản 2 không có cờ mở rộng.

    • Cờ giai đoạn 2 bit được sử dụng trong quá trình hợp nhất. Các giai đoạn được ghi lại trong man git-merge:

      • 0: tệp thông thường, không trong xung đột hợp nhất
      • 1: căn cứ
      • 2: của chúng tôi
      • 3: của họ

      Trong xung đột hợp nhất, tất cả các giai đoạn từ 1-3 được lưu trữ trong chỉ mục để cho phép các hoạt động như thế nào git checkout --ours.

      Nếu bạn git add, thì giai đoạn 0 được thêm vào chỉ mục cho đường dẫn và Git sẽ biết rằng xung đột đã được đánh dấu là đã được giải quyết. TODO: kiểm tra cái này

    • Độ dài 12 bit của đường dẫn sẽ đi theo :: 0 01chỉ 1 byte kể từ khi đường dẫn làb

  • Cờ mở rộng 2 byte. Chỉ có ý nghĩa nếu "cờ mở rộng" được đặt trên các cờ cơ bản. LÀM.

  • 62(ASCII b): đường dẫn có chiều dài thay đổi. Độ dài được xác định trong các cờ trước, ở đây chỉ là 1 byte , b.

Sau đó xuất hiện 00: 1-8 byte đệm bằng 0 để đường dẫn sẽ được kết thúc bằng null và chỉ mục sẽ kết thúc bằng bội số của 8 byte. Điều này chỉ xảy ra trước phiên bản chỉ mục 4.

Không có phần mở rộng đã được sử dụng. Git biết điều này vì sẽ không còn đủ dung lượng trong tệp cho tổng kiểm tra.

Cuối cùng, có một tổng kiểm tra 20 byte ee 33 c0 3a .. 09 ab 49 94về nội dung của chỉ mục.


1
Rất thú vị. +1. Điều đó minh họa câu trả lời của riêng tôi độc đáo. Tôi tự hỏi nếu những kết quả đó sẽ thay đổi với Git 2.1+ mới nhất.
VonC

3
@NielsBom vâng, điều đó cũng sẽ làm việc. Khi diễn giải các chương trình, tôi thích thực hiện hai cách tiếp cận: đầu tiên theo kinh nghiệm để xem nó tạo ra kết quả gì và chỉ sau đó đọc nguồn. Nếu không, người ta có thể bị cuốn vào các trường hợp cạnh mã nguồn thậm chí không xuất hiện trên các đầu ra đơn giản. Tất nhiên, tôi đã xem xét các cấu trúc nguồn để giúp hướng dẫn cho tôi và mọi TODO đều có thể được giải quyết khi tôi đọc cách các cấu trúc đó được thao tác, đó là phần khó.
Ciro Santilli 郝海东 冠状 病 事件

1
@CiroSantilli 事件 法轮功 纳米比亚 威: Nếu tôi sửa đổi chỉ mục trong trình soạn thảo hex và cập nhật tổng kiểm tra 20 byte, có lệnh nào để cập nhật sha1 được lưu trữ trong các đối tượng khác không? (git phàn nàn chữ ký sha1 của chỉ mục bị hỏng) . Dữ liệu chỉ mục cũng được lưu trữ theo một cách hoàn toàn khác khi gửi qua các yêu cầu đẩy.
dùng2284570

1
@CiroSantilli 事件 法轮功 纳米比亚: Mục đích bảo mật. Chỉ cần tìm loại tấn công tập tin hình ảnh raster được biết đến áp dụng cho cơ sở dữ liệu / đối tượng git. (tất nhiên tôi biết hầu hết việc triển khai gần đây đều quan tâm đến viễn cảnh đó, nhưng có lẽ không phải là tất cả)  Vì vậy, tôi đặc biệt tìm kiếm các cấu trúc dữ liệu nhị phân cho biết độ dài của một mảng. (liên quan đến bộ đệm văn bản, có vẻ như chấm dứt null là tiêu chuẩn để cho biết số lượng hàng)
user2284570

1
Về git add, theo bạn TODO: bạn đúng. Nếu bạn có các mục chỉ mục ở giai đoạn cao (xung đột) tại một đường dẫn cụ thể, khi bạn git addcó đường dẫn đó, tất cả các mục chỉ mục ở giai đoạn cao sẽ bị xóa và bản sao thư mục làm việc sẽ được thêm vào ở giai đoạn 0. (Giải quyết xung đột).
Edward Thomson

11

Chỉ mục Git là khu vực tổ chức giữa thư mục làm việc và kho lưu trữ của bạn. Bạn có thể sử dụng chỉ mục để xây dựng một tập hợp các thay đổi mà bạn muốn cam kết cùng nhau. Khi bạn tạo một cam kết, những gì được cam kết là những gì hiện có trong chỉ mục này, không phải những gì trong thư mục làm việc của bạn.

Để xem những gì bên trong chỉ mục, hãy ra lệnh:

git status

Khi bạn chạy trạng thái git, bạn có thể xem tệp nào được dàn dựng (hiện trong chỉ mục của bạn), tệp nào được sửa đổi nhưng chưa được phân loại và hoàn toàn không bị theo dõi.

Bạn có thể đọc . Một tìm kiếm Google đưa ra nhiều liên kết, điều này khá tự cung cấp.


7
git statuskhông liệt kê tất cả các tập tin từ chỉ mục. Nó chỉ liệt kê những tập tin khác nhau giữa chỉ mục và thư mục làm việc. Để xem tất cả các tệp trong chỉ mục, bạn cần sử dụng git ls-files.
Akash Agrawal

1
@AkashAgrawal, git status làm trong tập tin chỉ mục danh sách thực tế, cho dù chúng khác nhau giữa chỉ số và workdir.
Acumenus

3
vâng, nó liệt kê MỘT SỐ tệp chỉ mục, nhưng nó không hiển thị cho bạn mọi thứ bên trong chỉ mục, đó là những gì câu nói của anh ấy trong câu trả lời của anh ấy nói. Điều đó giống như nói rằng có 2 quả bóng màu xanh lá cây và 3 quả bóng màu đỏ trong một hộp. Để xem những gì bên trong hộp, kéo ra 2 quả bóng màu xanh lá cây. Những gì Akash nói là chính xác nhất, để xem tất cả các tệp trong chỉ mục, hãy sử dụng git ls-files.
dave4jr

3
Thật. git statusliệt kê các tệp trong chỉ mục, có, nhưng không liệt kê tất cả các tệp trong chỉ mục. Giải thích làm thế nào git status thực sự hoạt động sẽ là một câu trả lời có lợi cho một số câu hỏi, mặc dù có lẽ không phải là câu hỏi này.
Edward Thomson

1
git statushiển thị trạng thái cây làm việc (sự khác biệt giữa cây làm việc và chỉ mục). Nó không thực sự hiển thị các chỉ số. git-scm.com/docs/git-status
wvducky

1

Đây là những gì bạn cần chính xác, sử dụng lệnh này.

$ 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

Chỉ mục Git là một tệp nhị phân (thường được lưu giữ .git/index) chứa danh sách các tên đường dẫn được sắp xếp, mỗi tên có quyền và SHA1 của một đối tượng blob;

git ls-filescó thể cho bạn thấy nội dung của chỉ mục. Xin lưu ý từ mà index, stagecachelà những điều tương tự trong Git: chúng được sử dụng thay thế cho nhau.

nhập mô tả hình ảnh ở đây

Chỉ mục Git, hoặc bộ đệm Git, có 3 thuộc tính quan trọng:

  1. Chỉ mục chứa tất cả thông tin cần thiết để tạo một đối tượng cây (xác định duy nhất).
  2. Chỉ mục cho phép so sánh nhanh giữa đối tượng cây mà nó xác định và cây làm việc.
  3. Nó có thể biểu diễn thông tin một cách hiệu quả về xung đột hợp nhất giữa các đối tượng cây khác nhau, cho phép mỗi tên đường dẫn được liên kết với đủ thông tin về các cây liên quan mà bạn có thể tạo hợp nhất ba chiều giữa chúng.

Nguồn :

  1. https://mincong.io/2018/04/11/git-index/
  2. https://medium.com/hackernoon/under Hiểu-git-index-4821a0765cf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.