Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
hgbook.pdf
Скачиваний:
50
Добавлен:
17.03.2015
Размер:
3.15 Mб
Скачать

За кулисами

4.4. Рабочий каталог

В рабочем каталоге Mercurial хранит точную копию файлов из репозитория в соответствии с одной из ревизий.

Рабочий каталог «знает» какую из ревизий он содержит. Когда вы обновляете рабочий каталог до определенной ревизии, Mercurial просматривает соответствующую ревизию манифеста и находит там, какие файлы он отслеживал в то время, когда была создана ревизия, и какая из ревизий каждого из этих файлов была текущей. Потом он пересоздает копию каждого из этих файлов с содержимым на момент фиксации ревизии.

Dirstate это особая структура, которая содержит знания о рабочий каталоге Mercurial. Она содержится в файле с именем .hg/dirstate внутри хранилища. Dirstate детализирует ревизию которая содержит в рабочем каталоге и все файлы, которые Mercurial отслеживает в рабочей директории. Он также позволяет Mercurial быстро сообщает об измененных файлах, записывая их время вытягивания и размеры.

Так же, как и у ревизии в revlog есть место для двух родителей (обычная ревизия — с одним родителем, и результат слияния двух ревизий — с двумя родителями), у dirstate тоже есть слоты для двух родителей. Когда вы выполняете команду hg update, ревизия, которую вы обновляете сохраняется в слоте «первого родителя», а во второй слот помещается нулевое значение. Когда вы выполняете hg merge с другой ревизией, первый родитель остается неизменным, а вторым родителем становится ревизия с которой вы осуществляете слияние. Команда hg parents показывает родителей текущего состояния каталога.

4.4.1. Что происходит, когда вы фиксируете изменения

(commit)

Dirstate хранит информацию о родительских ревизиях не только для своих целей. Mercurial сохраняет родительские ревизии состояния рабочего каталога как родителей новой ревизии во время коммита.

Рисунок 4.5. Рабочий каталог может иметь две родительские ревизии

На Рисунок 4.5, «Рабочий каталог может иметь две родительские ревизии» показано нормальное состояние рабочего каталога, с одной ревизией в качестве родителя. Эта ревизия — окончание ветки (tip) — самая последняя ревизия в репозитории, у которой нет детей.

39

За кулисами

Рисунок 4.6. После коммита у рабочего каталога появляются новые родители

Полезно думать о рабочем каталоге, как о «ревизии, которую я сейчас зафиксирую». Любая операция с файлами (добавление, удаление, переименование, копирование), о которой вы сообщили Mercurial, будет отражена в этой ревизии, так же как и изменение в тех файлах, состояние которых он уже отслеживает. У новой ревизии будут те же родители, что у рабочего каталога.

После фиксации Mercurial обновит родителей рабочего каталога таким образом, что первым родителем будет идентификатор новой ревизии, а вторым — нулевой идентификатор. Это показано на Рисунок 4.6, «После коммита у рабочего каталога появляются новые родители» Mercurial не изменяет файлы в рабочем каталоге при фиксации изменений, он всего лишь изменяет dirstate, чтобы запомнить новых родителей.

4.4.2. Создание новой головы (head)

Абсолютно нормально обновлять текущий каталог до ревизии, которая не является последней. Например, вы хотите знать, как выглядел ваш проект в прошлый вторник, или вы просматриваете ревизии, чтобы найти ту, в которой появилась ошибка. В подобных случаях обычное дело обновить рабочий каталог до интересующей ревизии и потом просматривать содержимое файлов в нём в том состоянии, в каком они были во время фиксации ревизии. Результат этих действий показан на Рисунок 4.7, «Рабочий каталог, обновленный до ранней ревизии».

Рисунок 4.7. Рабочий каталог, обновленный до ранней ревизии

40

За кулисами

Что произойдет, если мы сделаем изменения в то время, как рабочий каталог обновлен до более старой ревизии, а потом зафиксируем их? Mercurial поступит точно так, как я и говорил раньше. Родители рабочего каталога станут родителями новой ревизии. У новой ревизии не будет детей, так что она станет конечной ревизией. И с этого момента в репозитории будет две ревизии без детей, мы называем их головами (head). Вы можете посмотреть на то, что получилось на Рисунок 4.8, «После фиксации, сделанной в то время, как рабочий каталог был обновлен до ранней ревизии.».

Рисунок 4.8. После фиксации, сделанной в то время, как рабочий каталог был обновлен до ранней ревизии.

Примечание

Если вы новичок в Mercurial, то вам следует помнить о распространенной «ошибке» — использовании команды hg pull без аргументов. По умолчанию, hg pull не обновляет рабочий каталог, так что вы получаете новые ревизии в репозиторий, но каталог соответствует той же ревизии, что и перед выполнением команды. Если вы сделаете изменения и зафиксируете их, то вы создадите новую голову, потому что рабочий каталог не соответствует ни одной концевой ревизии. Чтобы совместить операции вытягивания и последующего обновления, запустите команду hg pull -u.

Я написал «ошибка» в кавычках, потому что все что вам нужно сделать, чтобы исправить эту ситуацию

— это выполнить hg merge, а потом hg commit. Другими словами, такая ситуация никогда не приводит к негативным последствиям, она просто приводит людей в замешательство. Позже мы обсудим пути обхода этой ситуации, а также почему Mercurial по умолчанию ведет себя таким образом.

41

За кулисами

4.4.3. Слияние изменений

Когда вы выполняете команду hg merge, Mercurial оставляет первого родителя рабочего каталога неизменным, а вторым родителем назначает ревизию, с которой вы осуществляете слияние (см. Рисунок 4.9, «Слияние двух голов»)

Рисунок 4.9. Слияние двух голов

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

Если ни одна из ревизий не изменяла файл, то ничего с ним не делать

Если одна ревизия изменила файл, а другая — нет, то создать измененную копию файла в рабочем каталоге

Если одна ревизия удалила файл, а другая — нет (или тоже удалила его), то удалить файл из рабочего каталога

Если одна ревизия удалила файл, а другая изменила его, то спросить пользователя что делать — оставить измененный файл или удалить его?

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

Если одна ревизия изменила файл, а другая переименовала или скопировала файл, то удостовериться, что изменения будут перенесены в файл с новым именем

На самом деле все сложнее — у слияния есть множество подводных камней, но вышеперечисленное — это основные решения, которые нужно принимать при слиянии. Как видите, большая часть из них полностью

42

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]