Mercurial: как внести поправки в последнюю фиксацию?

Я ищу git commit --amend в Mercurial, то есть способ изменить коммит, с которым связана моя рабочая копия. Меня интересует только последний коммит, а не произвольный ранний коммит.

Требования к этой процедуре внесения поправок:

  • если возможно, он не должен требовать каких-либо расширений. Он не должен требовать расширений не по умолчанию, то есть расширений, которые не поставляются с официальной установкой Mercurial.

  • если обязательство изменить - один из моих нынешних веток, новый руководитель создавать не следует. Если фиксация не является заголовком, может быть создан новый заголовок.

  • процедура должна быть безопасной, так что если по каким-либо причинам изменение не удастся, я хочу восстановить ту же рабочую копию и состояние хранилища, что и до внесения изменений. Другими словами, если само изменение может потерпеть неудачу, должна существовать отказоустойчивая процедура для восстановления рабочей копии и состояния хранилища. Я имею в виду "сбои", которые лежат в природе процедуры внесения изменений (например, конфликты), а не проблемы, связанные с файловой системой (например, ограничения доступа, невозможность заблокировать файл для записи,... )

Обновление (1):

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

Обновление (2):

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

Ответ 1

С выпуском Mercurial 2.2 вы можете использовать опцию --amend с hg commit, чтобы обновить последнюю фиксацию с текущей рабочей каталог

Из ссылка в командной строке:

Флаг -amend может использоваться для изменения родителя рабочего каталога с новым фиксатором, который содержит изменения в родительском объекте, в дополнение к тем, которые в настоящее время передаются по статусу hg, если таковые имеются. Старый коммит хранится в резервном комплекте в .hg/strip-backup (см. Hg help bundle и hg help unbundle о том, как его восстановить).

Сообщение, пользователь и дата берутся из измененного коммита, если это не указано. Когда сообщение не указано в командной строке, редактор откроется с сообщением измененной фиксации.

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

Ответ 2

У вас есть 3 варианта редактирования коммитов в Mercurial:

  1. hg strip --keep --rev -1 последний (1) коммит (ы), так что вы можете сделать это снова (см. этот ответ для получения дополнительной информации).

  2. Использование расширения MQ, которое поставляется с Mercurial

  3. Даже если он не поставляется с Mercurial, расширение Histedit стоит упомянуть

Вы также можете посмотреть страницу истории редактирования вики Mercurial.

Короче говоря, редактирование истории действительно сложно и не рекомендуется. И если вы уже отодвинули свои изменения, вы ничего не можете поделать, за исключением случаев, когда у вас есть полный контроль над всеми остальными клонами.

Я не очень знаком с командой git commit --amend, но AFAIK, Histedit - это то, что кажется самым близким подходом, но, к сожалению, оно не поставляется с Mercurial. MQ действительно сложен в использовании, но вы можете делать с ним почти все.

Ответ 3

эквивалент GUI для hg commit --amend:

Это также работает из TortoiseHG GUI (я использую v2.5):

Swich в представлении "Commit" или в представлении workbench выберите запись "рабочий каталог". Кнопка "Commit" имеет опцию "Изменить текущую версию" (нажмите стрелку раскрывающегося списка кнопки, чтобы найти ее).

enter image description here

          ||
          ||
          \/

enter image description here

Предостережение emptor:

Эта дополнительная опция будет включена только в том случае, если версия для меркуриума по крайней мере 2.2.0, и если текущая ревизия не является общедоступной, это не патч и не имеет дети. [...]

Нажатие кнопки вызовет 'commit -amend', чтобы "изменить" ревизию.

Подробнее об этом в канале dev THG

Ответ 4

Я настраиваю то, что написал krtek. Более конкретно, решение 1:

Предположения:

  • вы совершили один (!) набор изменений, но еще не нажали его
  • вы хотите изменить этот набор изменений (например, добавить, удалить или изменить файлы и/или сообщение фиксации)

Решение:

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

Откат действительно отменяет последнюю операцию. Его способ работы довольно прост: обычные операции в HG будут только добавляться к файлам; это включает фиксацию. Mercurial отслеживает длину файла последней транзакции и поэтому может полностью отменить один шаг, обрезав файлы до их старых длин.

Ответ 5

Предполагая, что вы еще не распространяли ваши изменения, вот что вы можете сделать.

  • Добавьте в свой .hgrc:

    [extensions]
    mq =
    
  • В вашем репозитории:

    hg qimport -r0:tip
    hg qpop -a
    

    Конечно, вам не нужно начинать с нуля или всплывать по всем патчам, поскольку для последнего достаточно одного поп файла (hg qpop) (см. ниже).

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

  • hg qpush -a; hg qfinish -a
  • удалите файлы .diff (неприменимые исправления) еще в .hg/patches (должен быть один в вашем случае).

Если вы не хотите вернуть все вашего патча, вы можете отредактировать его, используя hg qimport -r0:tip (или аналогичный), затем отредактируйте материал и используйте hg qrefresh, чтобы объединить изменения в самый верхний патч вашего стека. Прочтите hg help qrefresh.

Редактируя .hg/patches/series, вы можете удалить несколько патчей или изменить порядок. Если ваша последняя ревизия равна 99, вы можете просто использовать hg qimport -r98:tip; hg qpop; [edit series file]; hg qpush -a; hg qfinish -a.

Конечно, эта процедура сильно обескуражена и рискованна. Сделайте резервную копию всего, прежде чем делать это!

Как побочный элемент, я делал это два раза в репозиториях с частными хранилищами.

Ответ 6

Последние версии Mercurial включают расширение evolve которое предоставляет команду hg amend. Это позволяет вносить изменения в коммит, не теряя предыдоговую историю в вашем контроле версий.

hg изменить [ВАРИАНТ]... [ФАЙЛ]...

псевдонимы: обновить

объединить ревизию с обновлениями и заменить ее новой

Commits a new changeset incorporating both the changes to the given files
and all the changes from the current parent changeset into the repository.

See 'hg commit' for details about committing changes.

If you don't specify -m, the parent message will be reused.

Behind the scenes, Mercurial first commits the update as a regular child
of the current parent. Then it creates a new commit on the parent's
parents with the updated contents. Then it changes the working copy parent
to this new combined changeset. Finally, the old changeset and its update
are hidden from 'hg log' (unless you use --hidden with log).

См. Https://www.mercurial-scm.org/doc/evolution/user-guide.html#example-3-amend-a-changeset-with-evolve для полного описания расширения evolve.

Ответ 7

Может не решить всех проблем в первоначальном вопросе, но, поскольку, похоже, это фактическая статья о том, как mercurial может изменить предыдущую фиксацию, я добавлю информацию на 2 цента.

Если вы похожи на меня и хотите изменить только предыдущее сообщение о фиксации (исправить опечатку и т.д.) Без добавления каких-либо файлов, это будет работать

hg commit -X 'glob:**' --amend

Без каких-либо шаблонов включения или исключения hg commit по умолчанию будет включать все файлы в рабочем каталоге. Применение шаблона -X 'glob:**' исключит все возможные файлы, позволяя только изменять сообщение коммита.

Функционально это то же самое, что git commit --amend когда в index/stage нет файлов.