Незважаючи на те, що GIT НЕ зберігає дельти файлів, ви можете все-таки відкатати попередні версії файлів (необмежено разів?)


14

Я читав, що Git не зберігає дельти файлів. Якщо це правда, як він підтримує відкат файлів до попередніх версій? Якщо він зберігає весь файл, то місце на сховищі диска повинно бути незмінно великим. Чи повертається підтримка файлу Git і відновлюються файли версії 1? Він навіть підтримує концепцію версій, пов'язану з файлами? Це (я вважаю) важливо для мого розуміння системи VCS / DVCS та моїх потреб. Мені потрібно вміти порівнювати те, що я збираюся перевірити, з попередніми версіями.

Відповіді:


44

Git не викидає інформацію самостійно *. Усі попередні версії кожного файлу завжди доступні для ревертування, різниці, перевірок тощо.

Ціле дерево проти окремих файлів

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

# 10 foo.c-changes ago
git show $(git rev-list -n 10 --reverse HEAD -- foo.c | head -1):foo.c

# 10 whole-tree-changes ago
git show HEAD~10:foo.c

Переваги орієнтації на дерева, головним чином, здатність переглядати вчинки як одиницю взаємозалежних змін, внесених до різних частин дерева, загалом значно переважають над додатковими введеннями (які можна полегшити псевдонімами, сценаріями та ін.) Та часом процесора провів копання через минулі коміти.

Ефективність зберігання

Коли новий об'єкт (наприклад, файл із раніше небаченим вмістом) потрапляє в систему, він зберігається з простим (zlib) стисненням як "вільний об'єкт". Коли накопичиться достатньо вільних об’єктів (на основі параметра gc.autoконфігурації; або коли користувач виконує git gc або одну з команд упаковки нижнього рівня), Git збирає багато вільних об'єктів в єдиний "файл упаковки".

Об'єкти у пакувальному файлі можуть зберігатися як звичайні стислі дані (такі ж, як вільний об’єкт, щойно зв'язані з іншими об’єктами), або як стислі дельти проти якогось іншого об'єкта. Дельти можуть бути пов'язані між собою до настроюваних глибин ( pack.depth) і можуть бути зроблені проти будь-якого відповідного об'єкта ( pack.windowконтролює, наскільки широко Git шукає кращу базу дельти; версія базового файлу, який історично не пов'язаний, може використовуватися як база, якщо це призведе до отримання хороша дельта стиснення). Широта, що надає конфігурації глибини та розміру вікна, дає механізму стиснення дельти, часто призводить до кращого стиснення дельти, ніж простое стиснення «версія» проти «наступної» та «попередньої» в стилі CVS.

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

Дивіться, як Git зберігає об’єкти та розділи Packfile Книги Git Community . Також git pack-об'єкти керують сторінкою .

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


3
+1 лише за кількість та детальну інформацію про надану вами інформацію.
Тамара Війсман

3
Крім того, оскільки Git використовує знімки файлів, а не дельти, повернутися довгий шлях до історії насправді простіше. Уявіть, що вам потрібно переглянути файл із 20 комісій тому. За допомогою дельт потрібно скасувати 20 наборів змін; зі знімками ви просто захоплюєте правильний знімок. Чим довша ваша історія, тим більша перевага. І якщо ви хочете побачити різницю між поточною версією та цією, це лише одна різниця, а не вирішувати, що було зроблено, скасовано, перероблено тощо.
Натан Лонг

Кріс, ти, здається, маєш досить гарну ручку на внутрішніх місцях Git. Будь-який шанс, що ти можеш розмахувати на цьому? stackoverflow.com/questions/5176225/…
Натан Лонг

@ChrisJohnsen Будь ласка, допоможіть мені зрозуміти це. На основі сказаного, чи може Git отримати схожу (або кращу) ефективність зберігання, ніж Subversion? Я знаю, що якщо я буду робити файл з незначними змінами багато разів, дані вартістю 1 ГБ можуть бути збережені в 100 МБ. Чи може Git зробити те ж саме?
Аліреза Ноорі

@AlirezaNoori: Все залежить від характеру даних та змін, що вводяться (розмір файлу, стисливість файлу, розмір та розташування змін тощо). Щось подібне, безумовно, має бути можливим (залежно від специфіки). Загалом, файли пакетів Git можуть витягуватись із більшого вибору баз для його дельта-стиснення порівняно із суворо зворотно-хронологічними дельтами, якими користуються сервери SVN (використовуються? Я не стежу за розробкою SVN…). Якщо ви маєте на увазі якесь конкретне запитання, вам слід розглянути питання про нове запитання, що включає всі відповідні деталі.
Кріс Джонсен

1

Його можна прочитати на одній сторінці:

...

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

...

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

...

Таким чином, ви можете повернутися до попередніх версій файлу та порівняти два файли.


1

git насправді зберігає дельти файлів, але зберігає їх як дельту всього дерева файлів.

Щоб побачити відмінності між версіями, виконайте одну з наступних дій:

  1. git diff - показує відмінності між останньою перевіреною версією та файлами, які були змінені, але не git addзапущені на них.
  2. git diff - кешування - показує відмінності між попередньою версією та всіма файлами, які були git addзапущені, але не були скоєні
  3. git diff commitid - відображає відмінності між поточним робочим каталогом та попереднім коміксом, як зазначено в команді
  4. git diff commita..commitb - показує різницю між двома комітами , a і b. Коміти можуть бути також символічними назвами, як гілки або теги.

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