Должно ли рабочее дерево обязательно быть внутри клонированного проекта, который я клонировал?
Как ответил ElpieKay, нет, не нужно быть, но это нормально.Каждый репозиторий Git поставляется с одним - ну, каждый не голый репозиторий Git.(Вам пока не нужно беспокоиться о «голом репозитории», но это просто тот, у которого нет рабочего дерева, так что вы не можете использовать его для выполнения какой-либо работы. Это может показаться странным и странным.в таких местах, как GitHub, хранятся ваши репозитории.)
Является ли рабочее дерево виртуальной концепцией?
Я не уверен, что вы подразумеваете под этой фразой.Это концепция контроля версий , особенно в современных системах контроля версий.Они обычно разделяют вещи на файлы , которые фиксируются / регистрируются , и файлы , над которыми вы сейчас работаете .Зафиксированные файлы попадают в хранилище, где они хранятся в виде замороженного снимка, и те, над которыми вы активно работаете, где вы можете их использовать и изменять.Файлы рабочей формы попадают в рабочее дерево или рабочее дерево (существует несколько вариантов написания этого слова с дефисом или без него; используйте любое, что вам нравится).
В частности, для Git естьеще одна вещь, о которой вам нужно знать, и это то, что Git по-разному называет index , или область подготовки , или иногда кеш .Все это одно - одно понятие - у него всего три имен .Полезно сравнить Git с Mercurial, другой достаточно современной и очень похожей VCS, здесь, наряду с другими VCS: Mercurial и другие VCS do имеют репозиторий и рабочее дерево (или рабочее дерево), но не имеют индекс.Так что Git необычен.Вот как следует об этом подумать:
Файлы с фиксацией находятся в замороженных (только для чтения) снимках.Чтобы Git занимал меньше места, Git хранит их в специальном формате Git-only.Этот формат сжат, иногда очень сжат, так что некоторые другие программы могут его читать.
Файлы, над которыми вы работаете, попадают в ваше рабочее дерево, где вы можете работать с ними,Здесь они имеют свою обычную несжатую форму, и, конечно, вы можете перезаписать их.Вы также можете хранить в своем рабочем дереве файлы, которые Git не собирается фиксировать в моментальные снимки: это неотслеживаемых файлов.
Git's index является специальным посредником, своего рода посередине между коммитом и рабочим деревом.Файлы в индексе уже сжаты в формате Git-only, но они еще не commit (заморожены).Они на 100% готовы к быть подтвержденными, но еще не зафиксированными.
Запуск git commit
просто останавливает все файлы, которые есть в индексе прямо сейчас.Вот почему git commit
так невероятно быстр: если вы использовали другие VCS, многие из них очень медленны, когда вы запускаете их глагол «commit», потому что они тратят много времени на сканирование каталогов, сжатие файлов, подготовку их кбыть замороженнымВ некоторых VCS вы могли бы пойти выпить кофе в ожидании коммита.: -)
Если вы думаете об индексе как о , что Git совершил бы, если бы вы запустили git commit
прямо сейчас , у вас есть хорошее представление об индексе Git.Это, естественно, приводит к правильному определению отслеживаемого файла против неотслеживаемого файла: a отслеживаемого файла - это файл, который сейчас находится в индексе, так чтобудет в следующем коммите;файл неотслеживаемый - это файл, которого сейчас нет в индексе, но он находится в рабочем дереве.(Если файл не находится в или в индексе или в рабочем дереве, это просто не файл вообще.)
Есть еще кое-что важное: обратите внимание, что мы еще не упомянули слово branch .Это потому, что Git гораздо больше заботится о коммитах , чем о ветках .Эти коммиты - замороженные снимки, которые Git делает с git commit
- , составляют ваших веток, поэтому ветки появляются при наличии коммитов.Это делает коммиты самой важной частью: в Git ветка names , как и master
, в основном используется только для find коммитов.
Git isсильно отличается от многих других VCS здесь.В других VCS ветви очень важны, потому что коммиты существуют, потому что они находятся в ветвях.Таким образом, зависит от ответвлений.В Git все наоборот: сначала существуют коммиты, и только потом мы добавляем имена веток.Git позволяет нам перемещать имена вокруг , даже не меняя коммитов!
Истинное имя любого коммита - его большой уродливый хэш-идентификатор.Когда вы запускаете git log
, это печатает эти хэш-идентификаторы.Идентификатор хеша коммита никогда не меняется, потому что это реальное имя коммита. имя ветви - это просто читаемое имя, которое мы прикрепляем к некоторому коммиту, и затем, когда мы работаем, мы перемещаем читаемое человеком имя к последнему один.Поэтому, если мы начнем с небольшого репозитория всего с тремя коммитами, мы можем нарисовать его следующим образом, используя буквы вместо идентификаторов хеша:
A <-B <-C <--master
Имя master
запоминает хешИдентификатор последнего коммита, коммит C
здесь.Commit C
запоминает идентификатор commit B
.Git вызывает B
родитель из C
, так что C
является дочерним по отношению к B
.Между тем B
запоминает идентификатор своего родителя A
.A
это наш самый первый коммит, поэтому у него нет родителя.Мы говорим, что имя master
указывает на C
, а C
указывает на B
, что указывает на A
(и A
нигде не указывает).
Когда мы проверяем master
, мы действительно проверяем коммит C
.Это помещает копию всех замороженных снимков C
в оба индекса (в форме только для Git, но теперь мы можем перезаписать файлы) и в рабочем дереве (в обычной форме).Затем мы выполняем некоторую работу в рабочем дереве, и когда мы закончим работать, мы запускаем, например:
git add README.txt newfile.py
Это копирует версию work-tree каждого из этихфайлы в индекс.Если уже была индексная версия README.txt
, это заменяет индексную версию.Если newfile.py
действительно новый, это копирует его в индекс, так что теперь он отслеживается - и, за исключением того, что он сжат в форму только для Git, newfile.py
в индексе теперь совпадает св рабочем дереве.
Затем мы запускаем:
git commit
, который (после сбора сообщения журнала и т. д.) делает новый снимок D
из того, что находится в индексе:тот же старый existing_file.txt
, который был в C
, обновленный README.txt
и новый файл newfile.py
, возможно.Новый коммит D
имеет, в качестве своего родителя, коммит, который мы извлекли, то есть C
: D
хэш-идентификатор C
магазина, так что D
указывает на C
.D
, будучи новым коммитом, также получает новый уникальный идентификатор хеша: Git каким-то образом придумывает большой уродливый хэш-идентификатор (нам не нужно сильно беспокоиться о как , тем более что мыне может изменить его :-)).
Как последний трюк, git commit
записывает хэш-идентификатор D
в имя master
:
A <-B <-C <-D <--master
Так что теперьmaster
указывает на последний коммит, как всегда.Более того, поскольку Git только что сделал D
из , индекс, индекс и D
совпадают.Пока вы обновили все индексные файлы из всех файлов рабочего дерева, индекс и рабочее дерево также совпадают: все совпадает, а git status
говорит "чистое рабочее дерево".