Подтвердить что ты не робот

Что содержит индекс git ТОЧНО?

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


Обновление

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

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

4b9b3361

Ответ 1

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

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

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

Проблема Racy git дает более подробную информацию об этой структуре:

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


Чтобы увидеть больше, ср. " git/git/Documentation/technical/index-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):

См. Коммит 77ff112, коммит 3255089, коммит abb4bb8, коммит c780b9c, коммит 3b1d9e0, коммит 371ed0d (10 октября 2018 г.) от Ben Peart (benpeart).
См. Коммит 252d079 (26 сентября 2018 г.) Нгуен Тай pclouds Дуй (pclouds).
(Объединено Джунио К Хамано - gitster - в комитете e27bfaa, 19 октября 2018 г.)

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

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

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

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

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


В результате (с использованием IEOT) совершить 7bd9631 очистить функцию read-cache.c load_cache_entries_threaded().

См совершать 8373037, совершать d713e88, совершают d92349d, совершают 113c29a, совершают c95fc72, совершают 7a2a721, совершают c016579, совершают be27fb7, совершают 13a1781, совершают 7bd9631, совершают 3c1dce8, совершают cf7a901, совершают d64db5b, совершают 76a7bc0 (09 мая 2019) от Jeff King (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.

Ответ 2

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

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

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

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

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

Основные структуры, определяющие индекс, находятся в cache.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 анализ

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

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 в hex:

      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 сохраняет свое состояние: fooobar.com/questions/22530/...

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

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

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

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

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

    • 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 над содержимым индекса.

Ответ 3

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

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

git status

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

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

Ответ 4

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

$ 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