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

Чому хеш коміту залежить від усієї попередньої історії і як Git перевіряє цілісність даних?

Хеш коміту обчислюється з усього вмісту коміту:

git cat-file -p HEAD
# tree 3c4e9cd789d88d8d89c1073707c3585e41b0e614
# parent 84ba0356e6199a1cb8a555fef6d09aebe1c203f1
# author Olena <olena@example.com> 1759500000 +0300
# committer Olena <olena@example.com> 1759500000 +0300
#
# Add invoice export

У нього входять хеш дерева (знімок усіх файлів) і хеш батьківського коміту. А хеш батька, у свою чергу, залежить від його батька - і так до першого коміту.

Наслідок - ланцюжок, як у блокчейні: зміна будь-чого в старому коміті (файлу, повідомлення, автора, навіть дати) дає новий хеш цього коміту, отже нові хеші всіх його нащадків. Тому:

  • один хеш гарантує всю історію: якщо у вас і в колеги main вказує на той самий хеш, у вас ідентичні всі файли й уся історія до цього моменту;
  • непомітно підмінити старий коміт чи файл неможливо - зміниться хеш, і це видно;
  • переписування історії (rebase, commit --amend) завжди створює нові коміти з новими хешами - звідси конфлікти з колегами, які вже мають старі.

Чому коміти з однаковим вмістом мають різні хеші: у коміті є час і автор. Два однакові git commit з різницею в секунду - різні коміти. Тому cherry-pick одного коміту у дві гілки дає два різні хеші.

Перевірка цілісності - git fsck:

git fsck
git fsck --full --strict

Перевіряє, що кожен об'єкт відповідає своєму хешу, всі посилання (з коміту на tree, з tree на blob-и) ведуть на існуючі об'єкти, і повідомляє про пошкоджені, відсутні й недосяжні об'єкти.

Де це корисно:

  • після збою диска чи синхронізації .git через хмарні сервіси;
  • fetch і clone перевіряють об'єкти автоматично (transfer.fsckObjects вмикає повнішу перевірку), тож пошкоджені дані з сервера не потраплять у ваш репозиторій непомітно.

Обмеження: хеш захищає від випадкових пошкоджень і непомітної підміни, але не доводить авторство - ім'я й пошту в коміті може вписати будь-хто. Для цього існують підписані коміти.

Докладніше в документації: git fsck

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