Mercurial cherry picking изменения для фиксации

скажем, я внес много изменений в свой код и мне нужно только зафиксировать несколько из этих изменений. Есть ли способ сделать это в mercurial? Я знаю это darcs имеет такую функцию, как эта.

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

10 ответов


MQ, как упоминал Чад, один из способов. Есть также более легкие решения:

  • запись расширения который работает примерно так же, как запись darcs. Он распространяется с mercurial.
  • отложить расширение что позволяет вам "откладывать" определенные изменения, позволяя вам фиксировать только подмножество ваших изменений (те, которые не откладываются)

Если вы используете TortoiseHg 1.x для Windows, эта функция реализована красиво прямо из коробки (не требуется расширения).

  1. запустите инструмент фиксации TortoiseHg.
  2. Выбрать файл, для которого вы только хотите зафиксировать подмножество изменения.
  3. нажмите на ломоть Вкладка выбор на панели предварительный просмотр.
  4. дважды щелкните или используйте пробел, чтобы переключить, какие изменения должны быть включено в обязательство.

на TortoiseHg 2.x вкладка выбора ломоть теперь исчезла. На его месте находится Shelve tool. Она имеет несколько больше возможностей, чем старый выбор ломоть. Эти новые функции приходят за счет некоторой дополнительной сложности.

enter image description here

обратите внимание, что нет необходимости явно включать расширение Mercurial Shelve при использовании этой функции. По словам Стива Борхо( ведущий разработчик TortoiseHg) в ответ на другой вопрос TortoiseHg: " у нас есть локальная копия расширения полки и позвонить в него напрямую."


на TortoiseHg 2.7+, эта функциональность была улучшена и повторно введена. Теперь он встроен непосредственно в инструмент фиксации:

example of change selection in the commit tool

обратите внимание в списке файлов слева, что верхний файл отмечен, чтобы указать, что он будет включен, второй файл не отмечен потому что он не будет включен,а третий файл, образец.txt, заполняется (индикатор null checkbox), потому что только выбранные изменения из этого файла будут включены в фиксацию.

изменение образец.txt, который будет включен, проверяется в нижней правой части выбора изменения изображения. Изменения, которые будут исключены снят и сравнения недоступна. Также обратите внимание, что значок для инструмента shelve по-прежнему доступен.


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

допустим, у вас есть такая история:

---O---O---A---B---C

первый пример-сквош коммитов A, B и C. Первый init mq:

$ hg qinit

теперь мы необходимо "импортировать" коммиты A, B и C в очередь исправлений. Предположим, что это последние 3 коммита. Мы можем использовать синтаксис ревизии "-N", чтобы импортировать их следующим образом:

$ hg qimport -r -3:-1

это означает импорт в виде патчей из 3 патчей до последней фиксации. Вы можете проверить состояние этих патчей с hg qseries. Он должен показать что-то вроде этого:

$ hg qseries
101.diff
102.diff
103.diff

где числа 101, 102 и 103 соответствуют локальным номерам ревизий коммитов A, B и C. Теперь эти патчи применяется, что означает, что изменения, которые они описывают уже в рабочей копии. Вы можете избавиться от изменений рабочей копии и удалить их из истории коммитов, сохранив их только в форме патча, используя hg qpop. Вы можете либо сказать hg qpop; hg qpop to pop изменяет C и B из стека или указывает патч для "pop to". В этом случае было бы что-то вроде этого:

$ hg qpop 101.diff
now at: 101.diff

теперь у вас есть патчи для коммитов B и C в патче очередь, но они не применяются (их изменения были "потеряны" - они существуют только в области очереди исправлений). Теперь вы можете сложить эти патчи в последний, т. е. мы создадим новую фиксацию, эквивалентную сумме изменений A+B+C.

$ hg qfold -e 102.diff 103.diff

это покажет ваш редактор, так что вы можете изменить сообщение коммита. По умолчанию сообщение будет конкатенацией сообщений фиксации для изменений A, B и C, разделенных звездочками. Самое приятное здесь то, что hg qfold будет вкладка-заполните исправления, если вы используете bash и имеете сценарий завершения hg. Это оставляет историю такой, где A+B+C-это одна фиксация, которая представляет собой комбинацию 3 патчей, которые нас интересуют:

---O---O---A+B+C

другой вариант использования-если у нас такая же история, как и раньше, но мы хотим удалить патч B и объединить A+C. Это очень похоже на выше на самом деле. Когда вы доберетесь до шага qfold, вы просто сложите последний коммит, а не последние 2 commits:

$ hg qfold -e 103.diff

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

$ hg qunapplied
102.diff

история теперь выглядит так, где A+C-это одна фиксация, которая объединяет изменения A и C:

---O---O---A+C

окончательный вариант использования может заключаться в том, что вам нужно применить только commit C. вы сделаете это, запустив qimport, как указано выше, и вы выскочите все патчи, которые вы не хотел:

$ hg qpop -a

флаг-A означает всплывающие все патчи. Теперь вы можете применить только тот, который вы хотите:

$ hg qpush 103.diff

это оставляет вас с этой историей:

---O---O---C

как только вы закончите со всем этим, вам нужно, чтобы закончить очередь возиться. Это можно сделать с помощью:

$ hg qfinish -a

Итак, мы здесь. Теперь вы можете запустить hg push и совершить только то, что вы хотите, или hg email последовательный патч в список рассылки.


Я чувствую, что я что-то упускаю, потому что никто не предлагал это уже.

обычная команда "HG commit" может использоваться для выборочного выбора того, что нужно зафиксировать (вам не нужно фиксировать все ожидающие изменения в локальном рабочем каталоге).

Если у вас есть набор таких изменений:

M ext-web/docroot/WEB-INF/liferay-display.xml
M ext-web/docroot/WEB-INF/liferay-portlet-ext.xml
M ext-web/docroot/WEB-INF/portlet-ext.xml

вы можете зафиксировать только два из этих изменений...

hg commit -m "partial commit of working dir changes" ext-web/docroot/WEB-INF/liferay-display.xml ext-web/docroot/WEB-INF/liferay-portlet-ext.xml

не очень удобно из командной строки, потому что вы должны ввести вручную файлы для выборочной фиксации (против процесса флажка GUI, такого как tortoise), но это примерно так же просто, как он получает и не требует расширений. И файл-подстановка, вероятно, может помочь уменьшить набора текста (как это было выше, как совершенные файлы уникальной акции "система" в их пути.


можно использовать запись расширения, который распространяется с Mercurial.

вы должны включить его в свой ~/.hgrc файл сначала, добавив его в :

[extensions]
record=

тогда, просто наберите hg record вместо hg commit, и вы сможете выбрать, какие изменения в какие файлы вы хотите зафиксировать.

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


прошло некоторое время. Кажется, лучший вариант сейчас hg commit --interactive


Я считаю Очереди Mercurial заполняет эту роль для Mercurial. Есть очень хороший учебник связаны там.


попробуйте qct (Qt Commit Tool). Он имеет функцию "выбрать изменения", которая запускает 3-полосный инструмент слияния для отмены отдельных изменений. После фиксации этих изменений вы "отстегнула" вернуться.


Я использую commit-patch. Это скрипт, который позволяет редактировать разницу перед фиксацией. Это действительно хорошо с diff-mode Emacs и VC-mode.

в прошлом я использовал crecord, но у него есть ошибки, связанные с unicode (на самом деле расширение записи имеет ошибки, от которых зависит crecord).


сначала вы должны забыть все, что вы когда-либо знали о GUI и вернуться к командной строке. Далее из командной строки сделайте следующее:

HG stat > список файлов.txt

Это передает все ваши измененные файлы в текстовый файл под названием filelist.txt

затем отредактируйте свой список файлов, чтобы включить только файлы, которые вы хотите зафиксировать.

наконец зафиксировать с помощью набора файлов sytnax:

HG commit "set: 'listfile:тест.txt'"