Як git зберігає файли?


225

Щойно я почав вивчати git, і для цього я почав читати книгу спільноти Git , і в цій книзі вони кажуть, що SVN та CVS зберігають різницю між файлами і що git зберігає знімок усіх файлів.

Але я насправді не зрозумів, що вони розуміють під знімком. Чи справді git робить копію всіх файлів у кожному комісі, тому що я зрозумів з їх пояснення.

PS: Якщо у когось є краще джерело для вивчення git, я би вдячний.


20
Ось блискучий пост, який докладно пояснює, як працює git. Те, що ви шукаєте - це, мабуть, пункт про об’єктну базу даних.
greg0ire

Відмінна стаття, що містить посилання на інші чудові ресурси. Я розважався з ними пару годин.
mihai

2
Я знайшов цю справді приємну статтю, що описує git зсередини: maryrosecook.com/blog/post/git-from-the-inside-out
Сумуду

Відповіді:


275

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

Отже, знімок - це в основному фіксація, посилаючись на зміст структури каталогів.

Деякі хороші посилання:

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

Лабораторія 12 ілюструє, як отримати попередні знімки


У книзі прогресу є більш вичерпний опис знімка:

Основна різниця між Git та будь-яким іншим VCS (включено Subversion та друзів) - це те, як Git думає про свої дані.
Концептуально більшість інших систем зберігають інформацію як список змін на основі файлів. Ці системи (CVS, Subversion, Perforce, Bazaar тощо) вважають інформацію, яку вони зберігають, як набір файлів та зміни, внесені до кожного файлу протягом часу

VCS на основі дельти

Git не думає і не зберігає свої дані таким чином. Натомість, Git сприймає свої дані більше як набір знімків міні-файлової системи.
Кожен раз, коли ви здійснюєте або зберігаєте стан свого проекту в Git, він в основному робить знімок того, як виглядають усі ваші файли в той момент, і зберігає посилання на цей знімок.
Для ефективності, якщо файли не змінені, Git знову не зберігає файл - лише посилання на попередній ідентичний файл, який він уже зберігав.
Гіт думає про свої дані так, як нижче:

VCS на основі знімків

Це важлива відмінність між Git і майже всіма іншими ДКС. Це змушує Git переглянути майже кожен аспект контролю версій, який більшість інших систем скопіювали з попереднього покоління. Це робить Git більше схожим на міні-файлову систему з неймовірними потужними інструментами, побудованими поверх неї, а не просто VCS.


Ян Худек додає цей важливий коментар :

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


4
@JanHudec хороший пункт. Я включив ваш коментар у відповідь для більшої наочності.
VonC

1
Хтось знає термін інформатики для шаблону зберігання схожих на Git, він же сховища значень на основі хешу? (або щось подібне)
Джоанн Верморель

34
У контексті актуального питання ОП перший абзац видається дійсно оманливим. Це поки ви не дійдете до останнього пункту , що ми дізнаємося , що, ах , да, то , Git робить «магазин [...] відмінність між файлами. На насправді хоче , що інформація була позначена до вершини і не поховала так глибоко. Тим НЕ менше, спасибі на принаймні, включаючи реальну історію десь у вашій відповіді;)
Джош О'Брайен

1
@NickVolynkin Чудово! Я радий, що ці відповіді знаходять більшу аудиторію.
VonC

1
Ще одна хороша книга: Git From The Bottom Up: ftp.newartisans.com/pub/git.from.bottom.up.pdf
Йонас Берлін

46

Git логічно зберігає кожен файл під його SHA1. Це означає, що якщо у сховищі є два файли з точно однаковим вмістом (або якщо ви перейменовуєте файл), зберігається лише одна копія.

Але це також означає, що коли ви модифікуєте невелику частину файлу і здійснюєте фіксацію, зберігається інша копія файлу. Git вирішує це за допомогою файлів пакету. Час від часу всі "розпущені" файли (власне, не лише файли, але й об'єкти, що містять інформацію про фіксування та каталогі), з репо збираються та стискаються у пакетний файл. Файл упаковки стискається за допомогою zlib. І подібні файли також стискаються дельта.

Цей самий формат також використовується при витягуванні або натисканні (принаймні, з деякими протоколами), тому ці файли не потрібно повторно стискати.

Результатом цього є те, що сховище git, що містить всю нестиснену робочу копію, нестиснені останні файли та стислі старі файли, як правило, порівняно невелике, у два рази менше, ніж розмір робочої копії. А це означає, що вона менше, ніж репо-SVN з тими ж файлами, навіть якщо SVN не зберігає історію локально.


1
ах, так що меркурій є більш просторовим
Бен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.