Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як влаштований файл .git/index і як Git швидко знаходить змінені файли?

.git/index - бінарний файл, що описує знімок для наступного коміту. Для кожного файлу він зберігає:

  • шлях, режим і хеш blob-а вмісту;
  • дані stat з файлової системи: розмір, час зміни (mtime, ctime), inode, пристрій, uid/gid;
  • номер стадії (stage) - для конфліктів злиття.
git ls-files --stage
# 100644 1f7a7a4... 0	composer.json
# 100644 e9c3d2b... 0	app/Models/User.php

git ls-files --debug app/Models/User.php   # разом з даними stat

Як git status працює швидко. Обчислювати хеш кожного файлу в проєкті з десятками тисяч файлів було б повільно. Тому Git спершу порівнює дані stat:

  1. якщо розмір і час зміни файлу збігаються з тими, що в індексі, - файл вважається незмінним без читання вмісту;
  2. лише для файлів з іншими stat Git читає вміст, хешує й порівнює з blob-ом в індексі;
  3. якщо вміст той самий (наприклад, файл перезбережено без змін), Git оновлює дані stat в індексі, щоб наступного разу не перевіряти.

«Racy git» - файл змінено в ту саму секунду, що й записано індекс: час збігається, хоча вміст інший. Git розпізнає цей випадок і перевіряє такі файли за вмістом.

Стадії при конфлікті: для конфліктного файлу індекс містить до трьох записів - стадія 1 (спільний предок), 2 (наша версія), 3 (їхня). git add після розв'язання замінює їх одним записом стадії 0.

git ls-files -u            # конфліктні записи
git show :2:config/app.php # наша версія
git show :3:config/app.php # їхня версія

Прапорці в індексі:

  • git update-index --assume-unchanged file - обіцянка Git не перевіряти файл (оптимізація для повільних файлових систем);
  • git update-index --skip-worktree file - ігнорувати локальні зміни відстежуваного файлу (локальна конфігурація). Обидва - локальні й не передаються іншим;
  • git ls-files -v показує такі файли малими літерами.

Для великих репозиторіїв: core.untrackedCache, core.fsmonitor і index.version=4 (стиснення шляхів) зменшують час status з секунд до мілісекунд.

Пошкоджений індекс («index file corrupt») не означає втрату історії: rm .git/index && git reset відтворить його з HEAD, зберігши файли робочого каталогу.

Докладніше в документації: Формат індексу Git

Схожі питання