Що насправді робить git, коли каже, що "вирішує дельти"?


187

Під час першого клонування сховища git спочатку отримує об'єкти (що досить очевидно), а потім витрачає приблизно стільки ж часу, "розв'язуючи дельти". Що насправді відбувається під час цієї фази клону?



1
Дивіться також, для Git 2.20 (Q4 2018) і більш дельта островів: stackoverflow.com/a/52458712/6309
VonC

Відповіді:


54

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

Ось розділ із розділу "Git Internals" книги Pro Git, який доступний в Інтернеті, який розповідає про це.


80
Ця відповідь невірна. Здається, описує, як працює Mercurial, а не Git. Він з'являється в пошуку Google щодо цього питання, тому я відчуваю необхідність відповідати. Git не зберігає відмінності між комітами як дельти; Git - це магазин "цілого об'єкта". Таким чином, Git не потребує "знімків", щоб показати будь-який файл, тому що історію файлів не потрібно реконструювати з дельт. Саме так працює Меркурій.
Nexus повідомляє

12
Єдине місце, де кодування дельти починає грати, - це файл упаковки, який призначений виключно для стиснення та передачі - це не змінює те, як Git "бачить" світ. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/… ) Будь ласка, дивіться відповідь araqnid нижче для точної відповіді.
Nexus повідомляє

4
Усі "знімки" в цьому контексті - це повна копія стану файлу, а не кодована дельтою версія. Як ви згадали, Git робить використання дельта-кодування в packfiles. Ніхто не сказав, що це «змінює те, як Гіт бачить світ»; будь ласка, перестаньте проектувати власні припущення.
Бурштин

2
Ваша відповідь досі неточна. "У Git також є одиничні знімки вмісту файлу, що зберігаються." - це не правильно. "" Вирішення дельт "- це крок, який стосується того, щоб все це залишалося послідовним." - це також невірно, відповідь аракніда нижче правильна.
Nexus повідомляє

1
Як описано в згаданій главі, Git завжди зберігає повний вміст файлів останньої версії. Попередні версії зберігаються як кодовані дельта файли, коли вони є "вільними" файлами. Періодично (за допомогою виклику git gcабо коли Git визначить це необхідним) Git буде стискати всі "вільні" файли в пакетний файл, щоб заощадити простір, і файл індексу в цьому пакетному файлі буде створено. Таким чином, zlib буде стискати з власним алгоритмом дельти, але Git використовує дельта-кодування для зберігання попередніх версій. Оскільки найпоширенішим та найчастішим доступом є остання версія, яка зберігається як знімок.
BrionS

118

Етапи git clone:

  1. Отримайте файл "pack" всіх об'єктів у базі даних repo
  2. Створіть індексний файл для отриманого пакету
  3. Ознайомтеся з ревізією голови (очевидно, що не є голим репо)

"Розв’язування дельти" - це повідомлення, показане для другого етапу, що індексує файл пакету ("git index-pack").

Пакетні файли не роблять мають в них власних ідентифікаторів об'єкта, лише вміст об'єкта. Таким чином, щоб визначити, що таке ідентифікатори об'єкта, git повинен зробити декомпресію + SHA1 кожного об'єкта в пакеті, щоб створити ідентифікатор об'єкта, який потім записується у файл індексу.

Об'єкт у пакувальному файлі може зберігатися як дельта, тобто послідовність змін, які вносяться до якогось іншого об'єкта. У цьому випадку git потребує отримання базового об'єкта, застосуйте команди та SHA1 результат. Сам базовий об'єкт, можливо, доведеться отримати, застосовуючи послідовність команд delta. (Незважаючи на те, що у випадку з клоном базовий об'єкт вже виникне, існує обмеження кількості виготовлених об'єктів, які зберігаються в пам'яті).

Підводячи підсумок, етап "розв'язання дельти" включає декомпресію та перевірку суми всієї бази даних РЕПО, що не дивно займає досить тривалий час. Імовірно, декомпресія та обчислення SHA1 насправді займає більше часу, ніж застосування команд delta.

У випадку наступного вилучення файл отриманого пакета може містити посилання (як бази об’єктів delta) на інші об'єкти, які, як очікується, вже мають. У цьому випадку приймаюча git фактично переписує отриманий файл пакету для включення будь-яких таких посилальних об'єктів, так що будь-який збережений файл пакету є самодостатнім. Можливо, саме звідси виникло повідомлення "розв'язання дельти".


7
Чи можна це паралелізувати?
brooksbp

Це дельта стиснення більше, ніж зберігання декількох об'єктів в одному потоці даних zlib?
fuz

1
@FUZxxl так, використовується алгоритм на зразок diff або xdelta для порівняння двох крапок і створення сценарію редагування
araqnid

@brooksbp: лише з обмеженнями. Оскільки об'єкту з id 103fa49 може знадобитися розшифрувати df85b51, але коли ви отримаєте 103fa49, df85b51 ще не існує (файли упаковки строго впорядковані хешами sha1). Отже, для всього, на що посилаються лише ті речі, які вже є, все легко, але для всього іншого вам доведеться почекати, поки воно буде отримане. І це дельта стиснення може бути вкладене, тому 103fa49 може знадобитися 4e9ba42, який, у свою чергу, потребує 29ad945, що, в свою чергу, потребує c9e645a ... ви отримаєте зображення. [так, я помітив, що пройшло> 4 роки;)]
Бодо Тісен

2
@brooksbp: Виявляється, я помилився, файл упаковки НЕ потрібно сортувати за sha1 хешами. Також під час написання git записує потрібні об'єкти перед об'єктами, які потребують їх. Отже, насправді ви повинні мати можливість паралелізувати це. Єдиний недолік, який залишається: оскільки ви не знаєте, які об’єкти вам знадобляться пізніше, вам доведеться відтворювати деякі знову і знову. Дивіться тут: kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen

4

Начебто Бурштин описує об'єктну модель, яку використовує Меркуріал або подібні. Git не зберігає дельти між наступними версіями об'єкта, а щоразу повні знімки об'єкта. Потім він стискає ці знімки за допомогою дельта-стиснення, намагаючись знайти хороші дельти для використання, незалежно від того, де в історії вони існують.


5
Насправді, хоча Git може зберігати сипучі об'єкти, вони не обов'язково завжди зберігаються як такі - оскільки вільні об’єкти можна видалити та замінити упакованим вмістом. Я не думаю, що відповідь Амбер ніде не говорила про наступні версії.
AlBlue
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.