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

Поиск и исправление ваших ошибок

В результате вы оказываетесь «там же, где и были» лишь с небольшим увеличением истории, в которой отражён откат.

У вас может возникнуть вопрос, почему Mercurial не фиксирует результат слияния, которое он выполнил. Причина в осторожном поведении Mercurial: очевидно, что слияние имеет значительно большее поле для возможных ошибок, чем просто отмена эффекта последней ревизии, так что ваша работа будет безопаснее, если вы сперва проверите (и протестируете!) результат слияния, и только потом его зафиксируете.

9.3.3.1. Всегда используйте опцию --merge

Фактически, поскольку опция --merge делает то что надо, независимо от того, является ли отменяемый набор изменений вершиной, или нет (т.е. не пытается зафиксировать возврат набора изменений, являющегося вершиной, поскольку в этом нет необходимости), вам следует всегда использовать эту опцию команды hg backout.

9.3.4. Получение бОльшего контроля над процессом возврата

До сих пор я рекомендовал вам всегда использовать опцию --merge, когда вы возвращаете изменение, однако команда hg backout позволяет вам выбрать, каким образом произвести фиксацию возврата изменения. Получение полного контроля над на тем, что происходит в процессе возврата — это то, что вам понадобится достаточно редко, однако полезно понимать, что именно команда hg backout делает в автоматическом режиме. Чтобы проиллюстрировать этот процесс, создадим копию репозитория, исключив возвращенные изменения, которые он содержит.

$ cd ..

$ hg clone -r1 myrepo newrepo adding changesets

adding manifests adding file changes

added 2 changesets with 2 changes to 1 files updating to branch default

1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd newrepo

Как и в предыдущем примере, Мы создадим третью ревизию, затем вернём в изначальное состояние, и посмотри что произошло.

$ echo third change >> myfile $ hg commit -m 'third change'

$ hg backout -m 'back out second change' 1 reverting myfile

merging myfile

0 files updated, 1 files merged, 0 files removed, 0 files unresolved

Наш новый набор изменений опять является потомком набора изменений, который мы возвращаем, а не того, который являлся вершиной. Команда hg backout вполне явно сообщает нам об этом.

$ hg log

--style compact

 

 

2[tip]

54d16b160c16 2012-02-02 14:09 +0000 bos

 

third change

 

 

 

1

37eb97592c2d

2012-02-02

14:09 +0000

bos

 

second

change

 

 

 

0

b48ef65237ab

2012-02-02

14:09 +0000

bos

 

first change

 

 

 

 

 

 

 

 

 

И снова чтобы увидеть что произошло, проще взглянуть на граф истории ревизий на рисунке Рисунок 9.3, «Возврат изменений с помощью команды hg backout». Он явно показывает, что когда мы использовали hg backout для возврата изменений, не являющихся вершиной, Меркуриал добавляет новый head в репозиторий (изменение, которое было зафиксировано, обозначено квадратом).

96

Поиск и исправление ваших ошибок

Рисунок 9.3. Возврат изменений с помощью команды hg backout

После выполнения команды hg backout, новый «backout» набор изменений становится родителем рабочего каталога.

$ hg parents

 

changeset:

2:54d16b160c16

tag:

tip

user:

Bryan O'Sullivan <bos@serpentine.com>

date:

Thu Feb 02 14:09:22 2012 +0000

summary:

third change

 

 

Теперь у нас есть два отдельных набора изменений.

$ hg heads

 

changeset:

2:54d16b160c16

tag:

tip

user:

Bryan O'Sullivan <bos@serpentine.com>

date:

Thu Feb 02 14:09:22 2012 +0000

summary:

third change

 

 

Давайте подумаем о том, что мы ожидаем увидеть, в содержимом myfile сейчас. Первое изменение, должно присутствовать, потому что мы никогда не возвращали его. Второе изменение должно пропасть, как изменение, которое мы вернули. Поскольку граф истории показывает третье изменение в качестве отдельной головы, мы не ожидаем увидеть третье изменение в myfile.

$ cat myfile first change

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

$ hg merge

abort: there is nothing to merge

$ hg commit -m 'merged backout with previous tip' $ cat myfile

first change

После этого графическая история нашего хранилища показана на Рисунок 9.4, «Ручное слияние возвращённых изменений».

97

Поиск и исправление ваших ошибок

Рисунок 9.4. Ручное слияние возвращённых изменений

9.3.5. Почему команда hg backout работает именно так

Вот краткое описание как работает команда hg backout.

1.Она гарантирует, что рабочий каталог будет «чистым», т.е., вывод команды hg status будет пустым.

2.Она запоминает текущего родителя рабочего каталога. Назовем эту ревизию оригинальной

3.Она не эквивалентна команде hg update, синхронизирующей текущий каталог с ревизией к которой вы хотите вернуться. Назовем эту ревизию откатываемой.

4.Она находит родителя ревизии, которую Вы хотите откатить. Назовем ее ревизия-родитель.

5.Для всех файлов, измененных в откатываемой ревизии, делается эквивалент команды hg revert -r parent, для восстановления их до содержимого которое они имели перед этой ревизией.

6.Результат сохраняется как новая ревизия. Эта ревизия имеет родителем откатываемую ревизию.

7.Если Вы указали ключ --merge в коммандной строке, делается слияние с оригинальной ревизией и результат слияния сохраняется как новая ревизия

Альтернативный способ реализации hg backout команда hg export применённую к откатываемому набору изменений как diff-у, а затем использовать опцию --reverse для команды patch для ликвидации последствий изменения без возни с рабочей директорией. Это звучит гораздо проще, но работает это не так хорошо.

Причина, по которой hg backout делает обновление, фиксацию, слияние, и ещё одну фиксацию используя механизм слияния в том, что это лучший шанс сделать работу хорошо, когда речь идет об сохранении всех изменения между ревизией которую мы откатываем, и текущей ревизией.

Если вы отказываясь ревизии, которая была 100 ревизий назад в истории вашего проекта, вероятность того, что команда patch сможет применить обратный diff аккуратно не велика, потому что вмешательство последующих

98

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