Яка різниця між HEAD, робочим деревом та індексом у Git?


488

Може хтось скаже мені різницю між HEAD, робочим деревом та індексом у Git?

З того, що я розумію, це всі назви для різних галузей. Чи правильне моє припущення?


Редагувати

Я це знайшов

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

Чи означає це, що HEAD та робоче дерево завжди однакові?


26
Стосовно вашої редакції: абсолютно ні. HEAD- фіксація на кінчику поточної гілки. Якщо ви тільки що перевірили гілку, тобто не маєте змінених файлів, то її вміст відповідає робочому дереву. Як тільки ви щось модифікуєте, воно більше не відповідає.
Каскабель

6
Я думаю, ви повинні прочитати це: think-like-a-git.net
Andrzej Duś

5
Я також додав би Staging Areaдо цього списку. Що HEAD, Working Tree, IndexіStaging Area
зелений

2
Останнє речення @ Jefromi's було б більш зрозумілим як:> Як тільки ви щось модифікуєте, робоче дерево більше не відповідає
команді

3
Для будь-якого читання цього в майбутньому найкращим способом по-справжньому зрозуміти деякі з цих відповідей є бачити та відчувати та візуально концептуалізувати, що відбувається: це найкращий інструмент для вивчення git коли-небудь: onlywei.github.io/explain-git-with -d3 / # fetchrebase
BKSpurgeon

Відповіді:


578

Ще кілька хороших посилань на ці теми:

alt текст

Я використовую індекс як контрольний пункт .

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

Примітки:

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

  2. Індекс являє собою один великий двійковий файл в <baseOfRepo>/.git/index, в якому перераховані всі файли в поточній гілки, їх SHA1 контрольні суми, мітки часу і ім'я файлу - це не інший каталог з копією файлів в ньому.

  3. Локальний репозиторій знаходиться прихований каталог ( .git) , включаючи objectsкаталог , що містить всі версії кожен файл в репозиторії (місцеві філії та копію віддалених філій) в якості стисненого файлу «Blob».

Не вважайте чотири "диски", зображені на зображенні вище, як окремі копії файлів репо.

alt текст

Вони в основному називають посиланнями на Git-коміти. Існує два основних типи посилань: теги та заголовки.

  • Теги - це фіксовані посилання, які позначають певний момент історії, наприклад v2.6.29.
  • Навпаки, голови завжди переміщуються, щоб відображати поточну позицію розвитку проекту.

alt текст

(Примітка: в коментував по Тімо Huovinen , ці стрілки не те , що коммітов вказують на це, це порядок документообігу , в основному , демонструє стрілки , як , 1 -> 2 -> 3 -> 4де 1це перше зобов'язання і 4останній)

Тепер ми знаємо, що відбувається в проекті.
Але щоб знати, що відбувається саме тут, зараз є спеціальна довідка під назвою HEAD. Він виконує дві основні цілі:

  • він повідомляє Git, які зобов’язуються приймати файли, коли ви оформляєте замовлення, і
  • він підказує Git, куди слід ставити нові коміти під час виконання зобов’язань.

Під час запуску git checkout refвін вказує HEADна визначений вами перелік та витягує з нього файли. Під час запуску git commitвін створює новий об'єкт фіксації, який стає дочірньою дією HEAD. Зазвичай HEADвказує на одну з голов, тому все виходить просто чудово.

alt текст


20
Прочитавши багато разів про git, я ніколи не розумію цього повністю, я дуже засмучений, я хочу використовувати слово f; Але я в спільноті! Ви згадали голови, але на зображеннях, наведених вище, завжди є одна головка, де r інші f ** ng голівки? "Зазвичай HEAD вказує на одну з голов, тому все виходить просто чудово". Прошу вас пояснити це, заява Ура.
Necktwi

12
@neckTwi HEAD - це поточний документ, з яким ви працюєте ( stackoverflow.com/a/964927/6309 ). Зазвичай це одна з "голів гілок" (одна з комісій, на яку посилаються гілки, що представляють кінчик зазначених гілок). Але ви можете оформити замовлення (і попрацювати над) будь-якими комісіями. Якщо ви витягаєте Комміт , який не є одним з філій (керівників), ви перебуваєте в режимі «стоїть окремо HEAD»: stackoverflow.com/a/3965714/6309
VonC

1
@Imray Я згоден, але саме так я знайшов ці фотографії 5 років тому ( hades.name/blog/2010/01/28/… )
VonC

11
Щодо індексу, я вважаю, що найкорисніше, що можна сказати, - це "індекс - це лише інша назва області постановки", як, наприклад, @ ashraf-alam. Я відчуваю, що більшість часу в обговоренні це називається областю постановки, тому я автоматично не встановив зв'язку, що це те саме, що і індекс.
Піт

1
@Pete Я згоден. Більш детальну інформацію про різницю між кешем і індексу см мій інший відповідь stackoverflow.com/a/6718135/6309
VonC

137

Різниця між HEAD (поточна гілка або останній дозволений стан на поточній гілці), індекс (ака. Область постановки) та робоче дерево (стан файлів у касі) описано в розділі "Три стани " розділу "Основи 1.3 Git " глава книги Pro Git Скотта Чакона (ліцензія Creative Commons).

Ось зображення, що ілюструють це з цієї глави:

Локальні операції - робочий каталог проти області індексів (індекс) і сховища git (HEAD)

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

Зауважте, що git commit -aпоетапно змінитимуться і виконуватимуться за один крок.


1
"Картина варта тисячі слів". Дякую Якубу .. І дякую за посилання.
Джойс Бабу

5
Примітка: working treeна working directoryсьогоднішній день, здається, віддають перевагу . Дивіться github.com/git/git/commit/…
VonC

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

@Jazimov Ви, напевно, маєте рацію, але, як він писав, він зняв цю картину з відомої книги Pro Git, і він надав посилання. Таким чином, якби картину можна було покращити або навіть помилитись, хтось повинен сказати авторам тієї книги ... Взагалі, я б хотів це зробити, але якщо чесно, я все ще початківець git і ще не став зрозумів, що ви сказали, тому я, безумовно, неправильна людина в такому випадку.
Бінарус

@Binarus: Небезпека оптового відтворення подібних зображень полягає в тому, що він служить для поширення "хибного представлення", зробленого одним автором / книгою. Я думаю, що тут йдеться про літеральні та функціональні інтерпретації: У прямому сенсі індекс насправді міститься в РЕПО, якщо ви визначаєте репо як усе, що знаходиться в папці .git. У функціональному сенсі, однак, індекс допомагає Git підтримувати DAG в репо і може вважатись істотою, що знаходиться поза ним.
Язимов

64

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

HEAD- це вказівник на гілку чи фіксацію, яку ви востаннє перевірили, і яка буде батьком нового комітету, якщо ви його зробите. Наприклад, якщо ви перебуваєте на masterгілці, тоді HEADви вказуватимете master, і коли ви здійснюєте, це нове зобов’язання буде нащадком редакції, на яку masterвказували, та masterбуде оновлено, щоб вказувати на нову комісію.

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


Велике спасибі за пояснення, Брайан. Отже, робоче дерево містить усі незапущені зміни. Якщо я здійснюю свої зміни за допомогою git commit -a, то в цей конкретний час моє Робоче дерево та індекс будуть однаковими. Коли я підштовхнусь до свого центрального репо, всі троє будуть однаковими. Я прав?
Джойс Бабу

3
@Vinod Досить. Ви можете мати у своєму робочому дереві файли, про які Git не знає, і ті не будуть зв'язані git commit -a(вам потрібно додати їх git add), тож у вашому робочому дереві можуть бути додаткові файли, що відповідають вашому індексу, локальній репо вашого віддаленого репо не мають.
Брайан Кемпбелл

2
@Vinod: Робоче дерево та індекс можуть бути однаковими, не виконуючи обов'язки (git add оновлює індекс з робочого дерева, а git checkout <path> оновлює робоче дерево з індексу). HEADвідноситься до останньої комісії, тому, коли ви здійснюєте, ви оновлюєте HEADсвою нову комісію, яка відповідає індексу. Натискання не має нічого спільного з цим - це робить гілки у відділеннях віддаленої відповідності у вашому місцевому репо.
Каскабель

45

Робоче дерево

Ваше робоче дерево - це файли, над якими ви зараз працюєте.

Індекс Git

  • "Індекс" git - це місце, де ви розміщуєте файли, які ви хочете скористатись сховищем git.

  • Індекс також відомий як кеш , кеш каталогів , поточний кеш каталогів , область постановки , інсценовані файли .

  • Перш ніж "зробити" (checkin) файли у сховище git, потрібно спочатку розмістити файли у git "index".

  • Індекс не є робочим каталогом: ви можете ввести таку команду, як git status, а git підкаже, які файли у вашому робочому каталозі були додані до індексу git (наприклад, за допомогою git add filenameкоманди).

  • Індекс не є сховищем git: файли в індексі git - це файли, які git запустить у сховище git, якщо ви використовували команду git commit.


1
Зауважте, що Git 2.5 принесе кілька робочих дерев ( stackoverflow.com/a/30185564/6309 ). +1
VonC

3
Я не впевнений, що "Індекс не є робочим каталогом" на 100% вірно. Він повинен бути "Індекс - це не робочий каталог, але він включає весь робочий каталог + зміни, які ви хочете зробити наступним". Доказ? перейдіть до сховища git, reset --hard HEADщоб переконатися, що ваш індекс == ваше робоче дерево. а потім: mkdir history && git checkout-index --prefix history/ -aРезультатом є дублювання всього вашого робочого дерева у вашому history/каталозі. Ergo git index> = git робочий каталог
Adam Kurkiewicz

3
Індекс не є робочим каталогом і не повинен включати робочий каталог. Індекс - це лише файл у сховищі git, який зберігає інформацію про те, що ви хочете зробити.
Бун

3
"" Індекс "містить знімок вмісту робочого дерева, і саме цей знімок приймається як вміст наступного коміту. Таким чином, після внесення будь-яких змін у робочий каталог та перед запуском команди на виконання, ви необхідно використовувати команду додати , щоб додати нові або змінені файли в індекс »( git-scm.com/docs/git-add )
Anth

3
@AdamKurkiewicz: доказ не вдається, якщо ви вперше echo untracked-data > untracked-file, до і після git reset --HARDі git checkout-indexкроки. Ви побачите, що файл, що не відслідковується , не знаходиться в historyкаталозі. Ви також можете змінювати як індекс, так і робоче дерево, незалежно, хоча змінити індекс без попереднього торкання робочого дерева важко (вимагає використання git update-index --index-info).
torek
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.