Git объединяет информацию для каждого файла или для каждого каталога? - PullRequest
0 голосов
/ 20 февраля 2019

В Perforce информация о слиянии (например, история слияния) указывается для каждого файла.В Subversion информация о слиянии указана для каждого каталога.В Git, информация о слиянии для файла или для каталога?

1 Ответ

0 голосов
/ 20 февраля 2019

Это ни то, ни другое.

Subversion здесь немного своеобразна, потому что она построена на системе, которая в основном работает с каталогами .Это означает, что вы можете, используя Subversion, проверить один конкретный каталог - ну, вроде: вы тоже получите его подкаталоги.Но он начинается с каталога: отсюда информация о слиянии на уровне каталога.

Основной единицей Git не является ни файл, ни каталог, а скорее commit .Вы не можете получить меньше целого коммита. 1 Когда вы запускаете git checkout <em>commit-specifier</em>, Git копирует полное дерево коммитов в ваш индекс / промежуточную область - это занимает относительно мало места;см. сноску 1 - затем копирует все эти файлы из индекса в ваше рабочее дерево , где вы можете работать с ними.

Каждый коммит Git представляет собой полный и полный снимок все файлов в вашем проекте или, точнее, все файлы, которые вы имели в своем индексе, когда вы делали коммит.Поскольку индекс начинается со всех файлов текущего коммита, он продолжает содержать все файлы и в следующем коммите.Коммит слияния здесь ничем не отличается от любого другого коммита: он содержит все файлы в их полном и полном великолепии, но сжат и заморожен, и Git-ified, способ, которым все файлы в любом коммите сжимаются и замораживаются и Git-ified,Поскольку они заморожены - вы не можете изменить любую часть любого коммита, когда-либо - они получают shared , если они не изменены, поэтому, если вы фиксируете 100 мегабайтфайл десять раз, или даже миллион раз, этот файл использует тот же объем дискового пространства, как если бы вы фиксировали файл размером 100 мегабайт только один раз - потому что, по сути, вы сделали .(Каждый коммит добавляет немного места над файлом для метаданных коммита, но если вы знакомы с идеей link в системе Unix / Linux, вы можете рассматривать каждый коммит какс жесткой ссылкой на один базовый файл.)

Между тем тот факт, что коммит равен , слияние записывается с помощью родительского хеш-идентификатора или идентификаторов, хранящихся вкаждый коммит.Каждый коммит запоминает необработанные хеш-идентификаторы (как бы истинное имя) коммита (ов), которые идут непосредственно перед этим конкретным коммитом.Для большинства коммитов есть только один такой хеш-идентификатор, и мы получим цепочку, обращенную назад, поэтому, если мы начнем с самого последнего коммита, хеш которого является каким-то большим уродливым хешем, мы простовызовите H, мы можем найти его родителя, чей хеш мы назовем G.Затем мы можем использовать G, чтобы найти родителя G, который мы назовем F, а затем использовать F, чтобы найти родителя F, и так далее:

... <-F <-G <-H

Нам просто нужно знать ответ на вопрос: Каков хэш-идентификатор последнего коммита в этой цепочке? Чтобы найти этот ответ, мы ищем название филиала , например master. имя содержит последний идентификатор хэша - и все!Все остальное происходит из коммитов.

Единственное, что особенного в коммите слияния - это то, что он записывает как минимум два родительских хэша:

...--F--G--H
            \
             M--...
            /
...--J--K--L

Информация о слиянии лежитв том, что у M есть два родителя, H и L.От M мы можем либо вернуться назад к H и следовать по этой цепочке назад, либо мы можем вернуться назад к L и следовать по этой цепочке назад.Все три коммита - M, H и L - представляют собой полные и полные снимки, поэтому, если мы хотим посмотреть, как коммит верхней цепочки H был изменен путем слияния с ним нижней цепочки LМы можем сравнить H и M.Если мы хотим увидеть, как коммит нижней цепочки L был изменен путем слияния с ним коммита верхней цепочки H, мы можем сравнить L и M.Это те же самые сравнения, которые мы проводим, когда, например, мы хотим увидеть, как изменился H: мы сравниваем G и H, которые являются двумя снимками, чтобы увидеть, что изменилось с G до H.

Если мы хотимгде две цепочки сначала расходятся , нам просто нужно более широкое представление:

...--E---F---G----H
      \            \
       \            M--...
        \          /
         I--J--K--L

Если родительский элемент F равен E, а родительский J равенI, чей родитель E, тогда мы можем видеть, что E была базой слияния в то время, когда мы объединяли H и L.Поскольку все коммиты заблокированы на все времена, если E была базой для слияния, то E по-прежнему является базой для слияния.

Это означает, что ответ на ваш вопрос: Существуетнет явной информации о слиянии вообще.Факт слияния и информация, необходимая для его повторения, подразумевается графом коммитов. Граф коммитов - это структура данных, которую вы (или Git) получаете, читая отдельные коммиты.Поскольку коммит является основной единицей, у вас всегда есть целый коммит. 2 В клоне shallow вы можете пропустить более ранние коммиты, но выможно заполнить их, возвращаясь туда, откуда вы клонировали, и «убирая» свой клон (или просто углубляя его достаточно далеко, чтобы увидеть то, что вам нужно видеть).


1 Git поддерживает концепцию разреженной проверки , но вы все равно получаете весь коммит. Все его файлов все еще копируются в ваш индекс.Разреженная проверка просто ограничивает, какие из этих файлов затем копируются из индекса в ваше рабочее дерево.Поскольку индексные копии в основном заморожены и могут напрямую совместно использовать копии при фиксации, это уменьшает необходимый объем дискового пространства, поскольку некоторые файлы никогда не нужно декомпрессировать из замороженной формы при фиксации.Следующий коммит, который вы делаете, если вы делаете другой, сделан из того, что находится в индексе, а не из того, что находится в рабочем дереве, поэтому новый коммит продолжает иметь всех файлов, несмотря наsparse checkout.

2 Git добавляет идею разрешения своего рода заполнителя, в виде пакетов промисора , где вы можете иметь коммит, но не хватает некоторыхего внутренних данных.Таким образом, сам коммит все еще будет основной единицей, но, хотя вы будете знать, что коммит C имеет дерево T , вам может не хватать объекта T Сам по себе, пока что-то явно не попросит об этом, и в этот момент Git попытается выполнить обещание, позвонив домой тому, кто дал обещание.На самом деле его пока нет в Git, но он медленно внедряется в базу кода.

Обратите внимание, что это несколько похоже на мелкие клоны.В случае с мелким клоном вы знаете, что у коммита C есть родительский P , но вам не хватает объекта P из-за мелкого трансплантата, который делаетнекоторые части Git притворяются, что C вообще не имеет родителей.Используя git fetch --deepen=<em>number</em>, вы можете сделать так, чтобы Git получил P , но, возможно, мелко привитый какой-то дедушка с P .Это просто заменяет точку мелкого трансплантата на новую для этого деда или полностью удаляет мелкий трансплантат, если вы получили всех родителей, например, через git fetch --unshallow.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...