Как с Mercurial я могу «сжать» серию ревизий в одну, прежде чем нажимать?

96

Допустим, у меня есть локальный и удаленный репозиторий Mercurial. Теперь я начинаю работать над функцией. Я работаю над этим, и когда я думаю, что это сделано, я фиксирую набор изменений. Попробовав еще немного, я обнаружил, что могу еще больше улучшить эту функцию, изменив что-то в коде. Я вношу изменения и подтверждаю. Спустя 20 минут я обнаружил ошибку в этой новой функции, поэтому исправляю ее и фиксирую ее.

Теперь у меня есть 3 набора изменений, которые я бы действительно хотел отправить в удаленный репозиторий как один набор изменений, например, с сообщением «Реализация функции X».

Как я могу сделать это без особых хлопот? Я считаю, что смогу сделать это с помощью патчей, но это, похоже, требует много работы.

Лукас
источник
40
Ясно, что не мне отговаривать вас от попыток сжать ваши ревизии, но вы, возможно, захотите принять во внимание, что половина ценности контроля версий приходится на ответы «почему», а не просто «что» месяцы и годы спустя. Точное представление о том, как появилась функция и на каких стадиях она может иметь ценность в будущем. Отказ от этого кажется таким ... неконтролируемым.
Ry4an Brase,
Это приводит к другому вопросу ... В чем разница между «histedit» и «collapse»
sylvanaar
1
collapse предоставляет подмножество функций histedit, а histedit имеет гораздо более интуитивный интерфейс пользователя.
Стефан Русек,
1
Он также предоставляет механизм для редактирования сообщения объединенной ревизии.
Стефан Русек,
1
@ Ry4an: На самом деле сжатие / сворачивание в некоторых случаях добавляет актуальности контролю версий. Без раздавливания у меня было бы два коммита каждый день, которые не имеют ничего общего с функциями или исправлениями ошибок, а предназначены для перемещения кода с ноутбука на рабочий стол и наоборот. Они просто добавляют шума в историю версий.
Джон Рейнольдс

Ответы:

39

Как насчет расширения "Свернуть" ?

Стив Лош
источник
20
Привет из будущего! Я просто искал ту же функциональность в Google, и, по-видимому, в настоящее время hg поддерживает это из коробки с помощью hg rebase --collapse. Просмотрите hg wiki о команде rebase. Поскольку этот вопрос является третьим общим результатом поиска и первым в stackoverflow, я подумал, что эта информация может быть полезной.
a.peganz 02
1
Привет из будущего !! Расширение rebase, похоже, нацелено исключительно на перемещение ревизий из одной ветки в другую. Да, есть опция --collapse, но она по-прежнему применима только при перемещении набора изменений между ветвями. См. < Mercurial-scm.org/wiki/… >
Брэд Острейхер,
3
Вы можете использовать hg rebasewith --collapseв одной ветке.
UuDdLrLrSs
52

Расширение histedit - это именно то, что вам нужно.

hg histedit -o

или

hg histedit --outgoing

откроет список исходящих ревизий. Из списка вы можете

  • Сверните 2 или более набора изменений, создав один набор изменений
  • Отбросьте изменения, удалив их из истории
  • Измените порядок изменений, как вам нравится.

histedit предложит вам новое сообщение фиксации свернутых наборов изменений, которые по умолчанию представляют собой два сообщения с разделением "\ n *** \ n".

Вы также можете получить аналогичные результаты, используя расширение mq, но это намного сложнее.

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

Стефан Русек
источник
спасибо, это именно то, что мне нужно. Было бы неплохо, если бы вы могли сделать это из TortoiseHg, но командная строка достаточно проста.
sylvanaar
21

Да, вы можете сделать это с помощью патчей: предположим, что ваша работа находится в наборах изменений от 100 до 110 включительно.

  1. Создайте патч:

    % hg export -o mypatch 100:110 --git

  2. Обновление до 99:

    % hg update 99

  3. Примените патч с --no-commit (иначе вы вернете все свои изменения):

    % hg import --no-commit mypatch

  4. Зафиксируйте все изменения сразу:

    % hg commit

  5. Теперь у вас есть две головы (110 и 111), которые должны быть эквивалентны с точки зрения файлов, которые они создают в вашем рабочем каталоге - возможно, различите их для здравомыслия, прежде чем удалять старые:

    % hg strip 100

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

Аркадий
источник
1
Отличный ответ, но есть необходимое условие: расширение MQ должно быть включено .
Крис Келли
Чтобы включить изменения в двоичные файлы, обязательно используйте параметр --git: например: «hg export -o mypatch 100: 110 --git». Для получения дополнительной информации см .: stackoverflow.com/a/12537738/ 367663 Я позволил себе исправить ответ.
Харлос Домингес
1
Кажется слишком сложным, почему бы hg strip --keepи нет, а затем фиксирует все за один коммит?
G. Demecki
@ G.Demecki Потому что это потенциально операция с очень большими потерями ..? Хотя MQ является излишним (и даже часто не рекомендуется), за исключением случаев, когда требуется такой рабочий процесс.
user2864740
@ user2864740 Возможно, вы правы, потому что я не эксперт по Mercurial. Но по умолчанию hg stripрезервная копия будет помещена в .hg/strip-backup/каталог. Думаю, это не так безопасно, git reflogно все же дает какое-то спасение.
G. Demecki
19

Если вы используете TortoiseHg, пользователь может просто выбрать две версии (используйте CTRL для выбора непоследовательных), щелкните правой кнопкой мыши и выберите «Сжать историю» .

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

Вы можете просто удалить старые списки изменений, если они вам больше не нужны: используйте для этого расширения MQ . Опять же, в TortoiseHg: щелкните правой кнопкой мыши первый список изменений, который нужно удалить со всеми его потомками, «Изменить историю -> Удалить» .

Джордж Мариан
источник
18

Я предпочитаю использовать mq для этого сворачивания с помощью TortoiseHg, как описано здесь . Однако это легко сделать из командной строки следующим образом:

hg qimport -r <first>:<last> 
    -- where <first> and <last> are the first and last changesets 
    -- in the range of revisions you want to collapse

hg qpop <first>.diff
    -- remove all except for the first patch from the queue
    -- note: mq names patches <#>.diff when it imports them, so we're using that here

hg qfold <next>.diff
    -- where <next> is <first>+1, then <first>+2, until you've reached <last>

hg qfinish -a
    -- apply the folded changeset back into the repository

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

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

Крис Филлипс
источник
4

hg collapseи hg histeditэто лучшие способы. Вернее, было бы лучше всего, если бы они работали надежно ... У меня histeditслучился сбой с дампом стека в течение трех минут. Collapseне намного лучше.

Думал, что могу поделиться двумя другими BKM:

  1. hg rebase --collapse

    Это расширение распространяется с Mercurial. У меня еще не было проблем с этим. Возможно, вам придется поиграть в некоторые игры, чтобы обойти hg rebaseограничения - в основном, ему не нравится перебазирование до предка в той же ветке, с именем или по умолчанию, хотя оно позволяет, если перебазирование между (именованными) ветвями.

  2. Переместите репозиторий ( foo/.hg) в рабочий каталог ( bar) и его файлы. А не наоборот.

Некоторые люди говорили о создании двух деревьев клонов и копировании файлов между ними. Или исправление между ними. Вместо этого легче перемещать .hgкаталоги.

hg clone project work
... lots of edits
... hg pull, merge, resolve
hg clone project, clean
mv work/.hg .hg.work
mv clean/.hg work/.hg
cd work
... if necessary, pull, nerge, reconcile - but that would only happen because of a race
hg push

Это работает до тех пор, пока настоящие репозитории, .hgдеревья, не зависят от рабочего каталога и его файлов.

Если они не независимы ...

Крейзи Глю
источник
В 2015 году histeditэто очень хороший вариант для этой задачи. Я все еще не доверяю ему, так как делаю git rebase -i, но он не дает сбоев ... по крайней мере, более новые версии оставят вас на временной ветке, если что-то пойдет не так, поэтому единственный раз, когда изменения будут удалены после фиксации новой ветки.
user2864740
2

Я никогда не использовал Mercurial, но это очень похоже на то, о чем не так давно говорил Мартин Фаулер в своем блоге:

http://martinfowler.com/bliki/MercurialSquashCommit.html

Джозеф
источник
Это выглядит более чем сложно, но спасибо за ссылку. Честно говоря, я надеюсь на какое-то волшебное расширение, которое будет делать именно то, что я хочу, например, fetch и transplant с наборами изменений pull и cherry-picking.
Лукас
0

Почему не просто hg strip --keepкомандовать?

Затем вы можете зафиксировать все изменения как одну фиксацию.

Г. Демеки
источник
@ Strawberry не дает ответа ?? Думаю, это прекрасно отвечает на вопрос автора. Вы можете уточнить свою точку зрения?
G. Demecki
Это древняя история, поэтому я откажусь от этого замечания, но одобренный ответ кажется более авторитетным справочником.
Strawberry
1
@ Strawberry Действительно, это древняя ветка. Но принятый ответ устарел, потому что Mercurial больше не требуется отдельное стороннее расширение для этой работы.
G. Demecki
0

HistEdit будет делать то, что вы хотите, но, вероятно, это излишне. Если единственное, что вам нужно, - это сложить несколько ревизий вместе, Collapse Extension сделает свою работу.

Стив Лош
источник
1
хотя он обеспечивает гораздо более простой в использовании и понимании пользовательский интерфейс, что более чем достаточно для его использования, но он также предоставляет механизм для редактирования объединенного сообщения набора изменений, что является еще одной вещью, которую я всегда хочу делать, когда я объединить ревизии.
Стефан Русек,
И проблема понимания только пользовательского интерфейса состоит в том, что на самом деле никто не понимает ... Во всяком случае, в прошлом, а histedit позволяет изменять «сообщения», а также изменять сообщения при «сворачивании». История идеальна; во всяком случае, расширение коллапса малоэффективно.
user2864740
0

Предположу , у вас есть два неопубликованных THISи THATфиксации в Mercurial и как их присоединиться к одну фиксации в THISточке ::

... --> THIS --> ... --> THAT --> ... --> LAST

Убедитесь, что ваши коммиты не опубликованы:

$ hg glog -r "draft() & ($THIS | $THAT)"

Обновление до LASTфиксации ::

$ hg up

и импорт фиксируется до THISв MQ ::

$ hg qimport $THIS::.

Отмените все исправления и примените только сначала THIS:

$ hg qpop -a
$ hg qpush
$ hg qapplied
... THIS ...

Присоединяйтесь с THAT::

$ hg qfold $THATNAME

ПРИМЕЧАНИЕ Чтобы найти имя, THATNAMEиспользуйте:

$ hg qseries

Примените все патчи и переместите их в историю репозитория:

$ hg qpush -a
$ hg qfinish -a

Мое сообщение в блоге по теме: « Объединение двух коммитов в Mercurial» .

гавенкоа
источник
0

Да, strip --keepработает на вопрос автора. Но он немного отличался от других, например, если у вас есть версии с 1 по 30, но вы хотите свернуть только версию 12-15. Другие решения работают, но нет strip --keep.

Фрэнк Тао
источник