Какой лучший способ отменить несколько наборов изменений в mercurial?
Является самым надежным методом, чтобы идти один за другим, используя команду отвода для каждого из многих наборов изменений, или есть способ создать один большой набор изменений, чтобы охватить целую кучу [edit: un-contiguous] Изменения.
Если один за другим, имеет ли дело порядок? (Должен ли идти один за другим?)
Отличается ли лучший метод, если на пути существуют слияния между различными подпроектами?
Неужели это имеет тенденцию идти гладко в вашем опыте?: -)
Ответы
Ответ 1
Существует опция --collapse
для rebase
.
Helgi answer можно обновить:
1 -- A -- 2 -- B -- 3 -- C -- 4 -- 5
\
C' -- B' -- A'
$ hg update --clean C
$ hg backout --rev C --message "Backed out changeset: C"
$ hg backout --rev B
$ hg commit --message "Backed out changeset: B"
$ hg backout --rev A
$ hg commit --message "Backed out changeset: A"
$ hg rebase --collapse --source C' --dest 5
$ hg commit --message "Backed out C, B, A"
что приведет к следующему
1 -- A -- 2 -- B -- 3 -- C -- 4 -- 5 -- C'B'A'
Однако поддержка в отдельной ветке может привести к [логическому] конфликту в последующем объединении.
1 -- A -- 2 -- B -- 3 -- X -- 4
\ \
B' -- A' -- M
if X
зависит от A
или B
, тогда M
будет иметь конфликт (по крайней мере логический конфликт).
Ответ 2
Если у вас нет слияний по пути, вы можете либо отменить каждое индивидуальное изменение (в обратном порядке), либо, если их много, сделайте это с помощью одного большого обратного патча.
Если у вас есть хорошие ревизии поверх тех, которые вам нужно отступить, лучше зафиксируйте обратный патч поверх самого последнего плохого набора изменений, а затем перетащите их на кончик ветки.
1 -- 2 -- A -- B -- C -- 3 -- 4
\
C'B'A'
$ hg up C
$ hg diff -r C:2 > backout.diff
$ hg import --no-commit backout.diff
$ hg ci -m "Backout A, B, C"
$ hg up 4
$ hg rebase -s C'B'A -d .
Будут проблемы, если вы хотите отменить изменения слияния, см. эту страницу вики для получения дополнительной информации.
В таком случае, если это возможно, подумайте о повторной работе ветки и лишении старой линии. В противном случае вам, возможно, придется отказаться от ветки вообще, избавиться от хороших изменений с помощью трансплантата или трансплантата.
Ответ 3
То, что я придумал, является неэлегантным, но выполнило свою работу, несмотря на то, что изменения, которые мне нужно было отступить, были перемешаны с другой работой и имели некоторое внутреннее ветвление. Вот что я сделал. (Комментарии и улучшения приветствуются.)
Получил список всех наборов изменений (которые я тогда использовал для генерации команд ниже):
hg log -r 'keyword(xyz)' --template '{rev}\n'
Создал патч для каждого набора изменений:
hg diff -p -U 8 --reverse -c 15094 > 15094.rev.patch
hg diff -p -U 8 --reverse -c 15095 > 15095.rev.patch
...
Затем применяется каждый обратный патч. Здесь порядок имеет последнее значение:
hg import -m "reversing changeset 15302" 15302.rev.patch
hg import -m "reversing changeset 15292" 15292.rev.patch
...
Этот процесс был прерван несколько раз для слияний, которые не прошли автоматически, когда мне пришлось вручную применить изменения в файле из его файла .rej и затем вручную зафиксировать, прежде чем собирать импорт там, где он был остановлен.
Наконец (в другом клоне... я упомянул, что сделал все это в клоне?) Я сжал весь набор обратных наборов изменений в один набор изменений с помощью hg histedit -o
и его команды fold.
Теперь у меня есть один набор изменений, который я могу отменить и применить, если я решит вернуть работу позже. Хотя, если я перейду через этот мост, я могу применить "вперед" патчи по частям снова, чтобы получить лучшую информацию о вине/аннотации)
Ответ 4
Вот как вы можете это сделать с TortoiseHg.
Конечно, вы можете сделать то же самое с командной строкой.
Учитывая эту историю, где вы не хотите избавляться от наборов изменений A, B и C:
1 -- 2 -- A -- B -- C -- 3 -- 4
Первое обновление до версии 2.
Затем переустановите первый из любых последующих изменений, которые вы не сохранили - в этом случае версия 3.
Ваша история теперь выглядит так:
1 -- 2 -- A -- B -- C
\
3 -- 4
Теперь обновите до версии 4.
И, наконец, используйте "Объединить с локальным", чтобы слить ревизию C в версию 4.
На этом этапе очень важно выбрать опцию "Отменить все изменения из версии слияния (другой)".
Описание может быть не самым логичным, но это означает, что вы объедините старый совет C назад к ветке по умолчанию - но без наборов изменений A, B и C.
Результат:
1 -- 2 -- A -- B -- C --
\ /
3 -- 4
Зафиксируйте, и все готово.
Ответ 5
Если вы не хотите, чтобы в вашей истории были внесены изменения в настройки резервного копирования, вы также можете сделать что-то еще:
Создайте клон вашего репозитория, но только до последнего набора изменений, от которого вы не хотите избавиться.
См. Mercurial: исправьте историю borked для примера, как это сделать.
Если ваш репозиторий был локальным, это все, что вам нужно сделать.
Но, если плохие изменения уже были перенесены в центральный репозиторий, вам нужен серверный доступ, чтобы удалить репозиторий там и заменить его на ваш клон.
Кроме того, если кто-то еще вытащил из репо с плохими наборами изменений, им нужно удалить и повторно клонировать (в противном случае плохие изменения снова возвращаются в центральное репо, как только один из других людей будет толкать снова).
Так что это зависит от того, подходит ли это решение для вас...