Mercurial - вернуться к старой версии и продолжить оттуда

249

Я использую Mercurial локально для проекта (это единственный репозиторий, в котором больше нет толкающих / тянущих к / из других мест).

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

Я немного запутался с командами branch/ revert/ update -Cв Mercurial. По сути, я хочу вернуться к версии 38 (в настоящее время на 45), и у моих следующих коммитов будет 38 в качестве родителя, и они будут продолжены. Мне все равно, будут ли редакции 39-45 потеряны навсегда или окажутся в собственной тупиковой ветке.

Какая команда / набор команд мне нужен?

Paolo
источник
6
Для всех, кто заинтересовался, это появилось на соответствующей боковой панели, которая является отличным объяснением возврата к обновлению: stackoverflow.com/questions/2506803/…
Paolo

Ответы:

150
hg update [-r REV]

Если позже вы совершите коммит, вы фактически создадите новую ветку. Тогда вы можете продолжить работу только над этой веткой или в итоге объединить существующую в нее.

фургон
источник
6
следующий коммит создаст новую ветку. Если вы не уверены, просто сделайте резервную копию вашего репозитория (с рабочей копией), попробуйте - не нравится результат -> начните с нуля бесплатно
van
Это сомнительный ответ, поскольку он объединяет ваши текущие изменения со старой ревизией, что, вероятно, и не нужно делать. Правильный ответ должен быть hg revert.
Тревор де Коеккук
Ответ в порядке, за исключением части о слиянии (я не думаю, что спрашивающий захочет слить).
ctrl-alt-delor
3
@NeonWarge REV - просто заполнитель для ревизии. Это может быть его номер, его хеш, закладка и так далее. Тревор: это не сомнительно, потому что ничего не объединяет. Не нужно.
DanMan
401

Вот шпаргалка по командам:

  • hg updateизменяет родительскую версию рабочей копии, а также изменяет содержимое файла в соответствии с новой родительской версией. Это означает, что новые коммиты будут выполняться с ревизии, до которой вы обновляете.

  • hg revertизменяет только содержимое файла и оставляет родительскую версию рабочей копии в покое. Вы обычно используете, hg revertкогда решаете, что не хотите сохранять незафиксированные изменения, сделанные вами, в файле в вашей рабочей копии.

  • hg branchзапускает новую именованную ветку. Думайте о названной ветви как о метке, которую вы назначаете наборам изменений. Так что, если вы это сделаете hg branch red, то следующие наборы изменений будут помечены как принадлежащие к «красной» ветви. Это может быть хорошим способом организации наборов изменений, особенно когда разные люди работают в разных ветвях, и вы позже захотите увидеть, откуда произошел набор изменений. Но вы не хотите использовать это в вашей ситуации.

Если вы используете hg update --rev 38, то наборы изменений 39–45 останутся в тупике - как бы мы его ни называли. Когда вы нажмете, вы получите предупреждение, так как вы создадите «несколько голов» в хранилище, куда вы нажимаете. Предупреждение есть, поскольку невежливо оставлять такие головы, так как они предполагают, что кто-то должен сделать слияние. Но в вашем случае вы можете просто пойти дальше, и, hg push --forceтак как вы действительно хотите оставить все как есть.

Если вы еще не отправили ревизию 39-45 в другое место, вы можете оставить ее в секрете. Это очень просто: с hg clone --rev 38 foo foo-38вами вы получите новый локальный клон, который содержит только до версии 38. Вы можете продолжить работу foo-38и добавить новые (хорошие) ревизии, которые вы создали. У вас все еще будут старые (плохие) ревизии в вашем fooклоне. (Вы можете переименовать клоны , однако вы хотите, например, fooчтобы foo-badи foo-38к foo.)

Наконец, вы также можете использовать, hg revert --all --rev 38а затем зафиксировать. Это создаст ревизию 46, которая выглядит идентично ревизии 38. Затем вы продолжите работать с ревизии 46. Это не создаст форк в истории таким же явным способом, как hg updateэто было, но, с другой стороны, вы не получите жалоб на наличие несколько голов. Я хотел бы использовать, hg revertесли бы я сотрудничал с другими, которые уже сделали свою собственную работу на основе ревизии 45. В противном случае, hg updateэто более явно.

Мартин Гайслер
источник
2
УДИВИТЕЛЬНЫЙ ответ. Я использовал hg revert --all --rev ##, и это спасло мою задницу: D
Ван Тоай Нгуен
1
Не лучше ли закрыть ветвь свисающей головы? Это предотвратит будущие предупреждения о хранилище. См. Stackoverflow.com/a/3688320/900130
Золтан
примечание: hg revert --all --rev xxx изменит локальные файлы, необходимые для возврата из вашего локального репо. Таким образом, вам нужно обновить до того, откуда вы хотите вернуться.
Винсент
Чтобы перейти с более ранней версии, мне сначала пришлось сделать возврат, а затем обновить. Это, как говорится, менее непрозрачное объяснение, чем большинство.
CodeLurker
30

Я только что столкнулся со случаем необходимости вернуть только один файл к предыдущей ревизии, сразу после того, как я сделал коммит и push. Сокращенный синтаксис для указания этих ревизий не охватывается другими ответами, поэтому вот команда, чтобы сделать это

hg revert path/to/file -r-2

Это -2вернет версию до последней фиксации, использование -1просто вернет текущие незафиксированные изменения.

Хайд
источник
1
Я считаю это чрезвычайно полезным. Конечно, для опции -r вы можете просто указать номер редакции
Alex
Вы также можете выбрать конкретную ревизию. напримерhg revert path/to/file -r478
Мэтт
7

ИМХО, hg strip -r 39лучше подходит для этого случая.

Это требует, чтобы расширение mq было включено, и имеет те же ограничения, что и «метод клонирования репо», рекомендованный Мартином Гейслером: если набор изменений каким-то образом был опубликован, он (вероятно) вернется к вашему репо в какой-то момент времени, потому что вы только изменили ваш местный репо.

magras
источник
Не знал об этом. Проще и чище, чем удалять и повторно клонировать репо. Спасибо.
Восстановить Монику - Нотмайнард
6

После использования hg update -r REVне было ясно в ответе о том, как зафиксировать это изменение, чтобы вы могли затем нажать.

Если вы просто попытаетесь зафиксировать после обновления, Mercurial не будет думать о каких-либо изменениях.

Сначала мне нужно было внести изменения в любой файл (скажем, в README), чтобы Mercurial узнал, что я сделал новое изменение, а затем я смог это зафиксировать.

Это тогда создало две головы как упомянуто.

Чтобы избавиться от другой головы перед толчком, я затем выполнил шаг No-Op Merges, чтобы исправить эту ситуацию.

Я тогда смог толкнуть.

Брайан Гершон
источник
Вы можете сделать commit --close-branchна старой ветке. Вы также push -fможете выдвигать новые головы, но это может привести к путанице относительно того, какая из них является текущей.
Ctrl-Alt-Delor
5

Ответы выше были самыми полезными, и я многому научился. Тем не менее, для моих нужд краткий ответ:

hg revert --all --rev ${1}

hg commit -m "Restoring branch ${1} as default"

где ${1}номер ревизии или название ветки. Эти две строки на самом деле являются частью скрипта bash, но они отлично работают сами по себе, если вы хотите сделать это вручную.

Это полезно, если вам нужно добавить оперативное исправление в ветку релиза, но нужно собирать по умолчанию (до тех пор, пока мы не получим правильные инструменты CI и не сможем строить из веток, а позже и с ветками релиза).

Брайан Карр
источник
1

Я бы установил Tortoise Hg (бесплатный графический интерфейс для Mercurial) и использовал его. Затем вы можете просто щелкнуть правой кнопкой мыши на ревизии, к которой вы, возможно, захотите вернуться - со всеми сообщениями о коммитах перед вашими глазами - и «Восстановить все файлы». Делает его интуитивно понятным и простым для прокрутки вперед и назад между версиями набора файлов, что может быть очень полезно, если вы хотите установить, когда проблема впервые появилась.

Джефф Кендалл
источник