Что в git index содержится ТОЧНО? - PullRequest
161 голосов
/ 03 ноября 2010

Что конкретно содержит индекс Git и какую команду я могу использовать для просмотра содержимого индекса?


Обновление

Спасибо всем заваши ответы.Я знаю, что индекс действует как промежуточная область, и то, что фиксируется, находится в индексе, а не в рабочем дереве.Мне просто интересно, из чего состоит индексный объект.Я предполагаю, что это может быть список имен файлов / каталогов, пар SHA-1, может быть, своего рода виртуальное дерево?

Есть ли в терминологии Git какая-либо команда plumbing , которую я могуиспользовать для просмотра содержимого индекса?

Ответы [ 4 ]

144 голосов
/ 03 ноября 2010

Книга Git содержит статью о , что включает в себя индекс :

Индекс представляет собой двоичный файл (обычно хранится в .git/index), содержащий отсортированный список имен путей, каждое из которых имеет разрешения и SHA1 объекта BLOB-объекта; git ls-files может показать вам содержимое индекса:

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

Задача Racy git дает некоторые дополнительные сведения об этой структуре:

Индекс является одной из наиболее важных структур данных в git.
Он представляет состояние виртуального рабочего дерева путем записи списка путей и имен их объектов и служит промежуточной областью для записи следующего объекта дерева, который будет зафиксирован.
Состояние является «виртуальным» в том смысле, что оно не обязательно должно и часто не совпадает с файлами в рабочем дереве.


Чтобы увидеть больше, ср. " мерзавец / мерзавец / Documentation / технический / индекс-format.txt ":

Файл индекса Git имеет следующий формат

Все двоичные числа расположены в сетевом порядке байтов.
Версия 2 описана здесь, если не указано иное.

  • 12-байтовый заголовок, состоящий из:
    • 4 байта подпись :
      Подпись {{D ',' I ',' R ',' C '} (расшифровывается как "dircache")
    • 4 байта номер версии :
      В настоящее время поддерживаются версии 2, 3 и 4.
    • 32-разрядное число записей индекса.
  • Количество отсортированных индексных записей .
  • Расширения
    Расширения идентифицируются по подписи.
    Дополнительные расширения можно игнорировать, если Git их не понимает.
    Git в настоящее время поддерживает кэшированное дерево и разрешает отмену расширений.
    • 4-байтовая подпись расширения. Если первый байт 'A' .. 'Z', расширение является необязательным и может быть проигнорировано.
    • 32-битный размер расширения
    • Расширение данных
  • 160-битный SHA-1 поверх содержимого файла индекса до этой контрольной суммы.

mljrg комментарии :

Если индекс - это место, где готовится следующий коммит, почему "git ls-files -s" ничего не возвращает после коммита?

Поскольку индекс представляет то, что отслеживается , и сразу после коммита то, что отслеживается, совпадает с последним коммитом (git diff --cached ничего не возвращает).

Итак, git ls-files -s выводит список всех отслеживаемых файлов (имя объекта, биты режима и номер этапа в выходных данных).

Этот список (отслеживаемых элементов) инициализируется содержимым коммита.
Когда вы переключаете ветку, содержимое индекса сбрасывается до коммита, на который ссылается ветка, на которую вы только что переключились.


Git 2.20 (Q4 2018) добавляет Таблица смещения записи индекса (IEOT) :

См. commit 77ff112 , commit 3255089 , commit abb4bb8 , commit c780b9c , commit 3b1d9e0 , коммит 371ed0d (10 октября 2018 г.) Бен Пирт (benpeart) .
См. коммит 252d079 (26 сентября 2018 г.) Нгуен Тай Нгок Дуй (pclouds) .
(Объединено Junio ​​C Hamano - gitster - в коммит e27bfaa , 19 октября 2018 г.)

ieot: добавить расширение таблицы смещения записи индекса (IEOT)

Этот патч позволяет указать стоимость загрузки индекса процессором, добавив дополнительные данные к индексу, которые позволят нам эффективно Поток загрузки и преобразования записей в кэш.

Это достигается путем добавления (необязательного) расширения индекса, которое является таблица смещений в блоки записей кэша в индексном файле.

Чтобы это работало для индексов V4, при записи записей в кэш он периодически «сбрасывает» префиксное сжатие, кодируя текущую запись, как будто имя пути для предыдущей записи полностью отличается, и сохраняет смещение этой записи в IEOT.
В основном, с индексами V4, он генерирует смещения в блоки сжатых префиксами записей.

С новой настройкой index.threads загрузка индекса теперь быстрее.


В результате ( использования IEOT ) commit 7bd9631 очистил функцию read-cache.c load_cache_entries_threaded() для Git 2.23 (Q3 2019).

См. коммит 8373037 , коммит d713e88 , коммит d92349d , коммит 113c29a , коммит c95fc72 , commit 7a2a721 , commit c016579 , commit be27fb7 , commit 13a1781 , commit 7bd9631 , commit 3c1dce8 , commit cf7a901 , commit d64db5b , commit 76a7bc0 (09 мая 2019) Джефф Кинг (peff) .
(Объединено с Junio ​​C Hamano - gitster - в коммит c0e78f7 , 13 июня 2019 г.)

read-cache: удалить неиспользуемый параметр из многопоточной загрузки

Функция load_cache_entries_threaded() принимает параметр src_offset что он не использует. Это происходит с момента его создания в 77ff112 (read-cache: загрузка записей кэша в рабочие потоки, 2018-10-10, Git v2.20.0-rc0).

Копирование в списке рассылки, этот параметр был частью более ранней итерации серии , но стал ненужным, когда код переключился на использование расширения IEOT.

59 голосов

Побитовый анализ

Я решил провести небольшое тестирование, чтобы лучше понять формат и более детально исследовать некоторые поля.

Результаты ниже одинаковы для Gitверсии 1.8.5.2 и 2.3.

У меня отмечены точки, которые я не уверен / не нашел с TODO: пожалуйста, не стесняйтесь дополнять эти точки.

Какдругие упоминали, что индекс хранится в .git/index, а не как стандартный объект дерева, и его формат является двоичным и задокументирован в: https://github.com/git/git/blob/master/Documentation/technical/index-format.txt

Основные структуры, которые определяют индекс, находятся в кеше.h , потому что индекс является кешем для создания коммитов.

Настройка

Когда мы запускаем тестовое хранилище с:

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

.gitКаталог выглядит так:

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

И если мы получим содержимое единственного объекта:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Получим a.Это означает, что:

  • index указывает на содержимое файла, так как git add b создал объект BLOB-объекта
  • , он хранит метаданные в файле индекса, а не в деревеобъект, поскольку был только один объект: BLOB-объект (в обычных объектах Git метаданные BLOB-объектов хранятся в дереве)

hd analysis

Теперь давайте рассмотрим сам индекс:

hd .git/index

Дает:

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

Далее мы заключим:

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

Сначала идет заголовок, определенный в: struct cache_header :

  • 44 49 52 43: DIRC.TODO: почему это необходимо?

  • 00 00 00 02: версия формата: 2. Формат индекса развивался со временем.В настоящее время существует версия до 4. Формат индекса не должен быть проблемой при совместной работе между различными компьютерами на GitHub, потому что пустые репозитории не хранят индекс: он создается во время клонирования.

  • 00 00 00 01: количество файлов в индексе: только один, b.

Далее начинается список записей индекса, определяемых struct cache_entry Здесь у нас только один.Он содержит:

  • набор метаданных файла: 8 байт ctime, 8 байт mtime, затем 4 байта: устройство, индекс, режим, UID и GID.

    Обратите внимание, как:

    • ctime и mtime совпадают (54 09 76 e6 1d 81 6f c6), как и ожидалось, поскольку мы не изменили файл

      первые байты - это секунды, начиная с EPOCH в шестнадцатеричном формате:

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

      Дает:

      Fri Sep  5 10:40:06 CEST 2014
      

      Именно тогда я и сделал этот пример.

      Вторые 4 байта - это наносекунды.

    • UID и GID 00 00 03 e8, 1000 в шестнадцатеричном формате: общее значение для однопользовательских настроек.

    Все эти метаданные, большинствокоторого нет в объектах дерева, позволяет Git проверить, быстро ли изменился файл, не сравнивая все содержимое.

  • в начале строки 30: 00 00 00 02:размер файла: 2 байта (a и \n из echo)

  • 78 98 19 22 ... c1 99 4e 85: 20 байт SHA-1 по сравнению с предыдущим содержимым записи.Обратите внимание, что согласно моим экспериментам с предполагаемым допустимым флагом , флаги, следующие за ним, не рассматриваются в этом SHA-1.

  • 2-байтовые флаги: 00 01

    • 1 бит: принять допустимый флаг.Мои исследования показывают, что в этом плохо названном флаге git update-index --assume-unchanged хранится его состояние: https://stackoverflow.com/a/28657085/895245

    • 1-битовый расширенный флаг.Определяет, присутствуют ли расширенные флаги или нет.Должно быть 0 в версии 2, у которой нет расширенных флагов.

    • 2-битный флаг стадии, используемый во время слияния.Этапы документированы в man git-merge:

      • 0: обычный файл, не в конфликте слияния
      • 1: base
      • 2:ours
      • 3: их

      Во время конфликта слияния все этапы 1-3 сохраняются в индексе, чтобы разрешить такие операции, как git checkout --ours.

      Если вы git add, то ступень 0 добавляется в индекс для пути, и Git будет знать, что конфликт был помечен как разрешенный.ТОДО: проверь это.

    • 12-битная длина пути, который будет следовать: 0 01: только 1 байт, поскольку путь был b

  • 2 байтарасширенные флаги.Имеет смысл только если «расширенный флаг» был установлен на базовые флаги.TODO.

  • 62 (ASCII b): путь переменной длины.Длина, определенная в предыдущих флагах, здесь всего 1 байт, b.

Затем следует 00: 1-8 байт заполнения нулями, так что путь будет нулевымзавершается, и индекс заканчивается кратным 8 байтам.Это происходит только до версии индекса 4.

Расширения не использовались.Git знает это, потому что в файле не осталось места для контрольной суммы.

Наконец, есть 20-байтовая контрольная сумма ee 33 c0 3a .. 09 ab 49 94 над содержимым индекса.

12 голосов
/ 03 ноября 2010

Индекс Git является промежуточной областью между вашим рабочим каталогом и вашим хранилищем.Вы можете использовать индекс для создания набора изменений, которые вы хотите зафиксировать вместе.Когда вы создаете фиксацию, то, что фиксируется, это то, что в данный момент находится в этом индексе, а не то, что находится в вашем рабочем каталоге.

Чтобы увидеть, что находится внутри индекса, введите команду:

git status

Когда вы запускаете git status, вы можете видеть, какие файлы размещены (в настоящее время в вашем индексе), которые изменены, но еще не созданы, и которые полностью не отслежены.

Вы можете прочитать this .Поиск Google выдает много ссылок, которые должны быть достаточно самодостаточными.

1 голос
/ 24 января 2019

Вот что именно вам нужно, используйте эту команду.

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