Могу ли я сквошить коммиты в Mercurial?

110

У меня есть пара коммитов, которые действительно должны быть одними. Если бы я использовал git, я бы использовал:

git rebase -i <some-commit-before>

а затем раздавите их.

Могу я сделать это в ртути? Если да, то как?

Р. Мартиньо Фернандес
источник

Ответы:

88

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

В качестве альтернативы, если вы хотите использовать расширение, вы можете использовать:

Ry4an Brase
источник
Да, я выудил этот ответ из одураченных вопросов, которые мне нравились в моем комментарии к общему вопросу. Я думаю, это ваш ответ на этот вопрос.
Ry4an Brase
4
Небольшое примечание: расширение Histedit распространяется с Mercurial 2.3 и новее. Вам просто нужно включить его.
Paidhi
1
В документе «Объединение наборов изменений» используются абстрактные концепции «репозиториев», как мне ссылаться на них? Например: hg -R oldrepo export ... выдает «abort: репозиторий oldrepo не найден!»
Александр Левчук
13
Просто пытаюсь раздавить 2 коммита. Действительно ли мне нужна вики-страница с 10+ командами или альтернативными расширениями?
Александр Левчук
3
См. Комментарии. Histedit теперь встроен, вам просто нужно включить его (потому что никакие команды по умолчанию не изменят историю)
Ry4an Brase
43

Мой любимый - hg strip --keepкоманда. И затем я фиксирую все изменения одним коммитом.

Для меня это самый быстрый и удобный способ, потому что я люблю совершать множество мелких коммитов во время своей повседневной работы;)


Примечание 1. Для включения stripнеобходимо встроенное расширение mq.
Примечание 2: Мой любимый клиент Git / Mercurial (SmartGit / Hg) добавляет --keepпараметр по умолчанию во время strip. И что еще удобнее: здесь есть опция join commits:]

Г. Демеки
источник
4
Полная команда для hg strip: hg strip --keep --rev [rev] Где revномер редакции первого коммита, который вы хотите сквошить с последним
Николас Форни
3
@NicolasForney Не совсем, --revне обязательно, полная командаhg strip --keep [rev]
Г. Демеки
Для меня доработка в 3.3.3 является обязательной: hg help stripдает hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV..., а пропуск ревизии дает мне abort: empty revision set.
Роман Старков
3
Использование hg strip- не лучшая идея. Это не совсем безопасно. Попробуйте hg histedit, может быть, даже попробуйте использовать расширение evolve.
Мартин Томсон,
Кажется, самый естественный способ для мерзавцев;)
foo
32

Расширение Rebase работало как шарм. Чтобы раздавить 2 коммита:

$ hg rebase --dest .~2 --base . --collapse

Точка - это ярлык для текущей версии.

Это еще проще, когда у вас есть несколько коммитов в ветке и вы хотите свернуть их все в один:

$ hg rebase --dest {destination branch (e.g. master)} --base . --collapse

Как это работает:

введите описание изображения здесь

(из http://mercurial-scm.org/wiki/RebaseExtension#Collapsing )

Мартин Коничек
источник
1
Где вы нашли "~ 2" для двух коммитов?
Mi-La
1
Это объясняется в теме о ревизиях, см. Hg help revsets.
markand
13

Если вы читаете этот ответ, вы можете забыть обо всех других вариантах, упомянутых в этом ответе, и использовать foldкоманду из расширения evolve .

evolveэто расширение mercurial, которое помогает нам иметь безопасную изменяемую историю, хотя оно все еще экспериментально. Вы можете использовать его путем клонирования его из репозитория и добавления его в .hgrc , как это.

[extensions]
evolve = ~/evolve/hgext/evolve.py

Предполагая, что вы клонировали репозиторий Evolve в своем домашнем каталоге. Теперь можно идти. Вы также можете обратиться за помощью по адресу hg help fold.

Сложить команду

Вы говорите foldсжать / свернуть линейную цепочку коммитов, которая не нарушается. Что делает fold, так это то, что он создает новый набор изменений, который содержит изменения из всех наборов изменений и помечает все эти изменения как устаревшие. Более подробно об этом можно прочитать в документации .

Теперь предположим, что у вас есть следующая история.

a -> b -> c -> d -> e -> f -> g

Вы хотите раздавить e, fи g. Ты можешь сделать

hg up g
hg fold -r e

Результат будет

a -> b -> c -> d -> h

где h- набор изменений, содержащий изменения из всех трех коммитов e, fи g.

Вы также можете складывать ревизии из середины истории, то есть не обязательно выбирать цепочку, которая включает подсказку. Предположим, вы хотите сбросить карты b, cи d. Ты можешь сделать

hg up d
hg fold -r b
hg evolve --all

Это приведет к

a -> i -> j

где iнаходится сложенный из ревизии b, c, dи jодно и то же , как набор изменений h. Обязательно прочтите руководство пользователя Evolve .

Pulkit Goyal
источник
Похоже, что rebase охватывает большинство (может быть, все?) Варианты использования этого расширения и, конечно же, тот, который задается в этом вопросе. Убийственная особенность этого расширения заключается в том, чтобы скрыть (а не удалить) заменяемые вами ревизии, но --keepопция перебазирования покрывает это (с последующей пометкой ревизий как секретных или использованием полосы после проверки результата). Даже перемещение ревизий между другими ревизиями возможно с помощью последовательности двух команд перебазирования.
Arthur Tacca
... плюс, если вы делаете что-то действительно сложное, вы всегда можете сначала клонировать локальное репо, чтобы использовать его в качестве резервной копии. Учитывая, насколько это редко (надеюсь!), Это меньше усилий, чем научиться использовать совершенно новое расширение.
Arthur Tacca
«NameError: имя 'execfile' не определено» - что означает, что Evolve написано на Python 2, который по сути является каменным веком.
Neil G
1
@NeilG mercurial еще не поддерживает Python 3.
Pulkit Goyal
2
@NeilG Да, сообщество Mercurial прилагает все усилия, чтобы получить поддержку py3 как можно скорее.
Pulkit Goyal
1

В Mercurial 4.8 (ноябрь 2018 г., 9 лет спустя) вы можете рассмотреть новую команду hg absorb( раньше это была экспериментальная функция ).

См. « Поглощение изменений фиксации в Mercurial 4.8 »

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

На техническом уровне hg absorbнаходит все незафиксированные изменения и пытается сопоставить каждую измененную строку с однозначной предыдущей фиксацией.
Для каждого изменения, которое может быть четко отображено, незафиксированные изменения поглощаются соответствующей предыдущей фиксацией. Коммиты, на которые повлияла операция, автоматически изменяются.
Если изменение не может быть сопоставлено с однозначной предыдущей фиксацией, оно остается незафиксированным, и пользователи могут вернуться к существующему рабочему процессу (например, используя hg histedit).

Логика автоматической перезаписи hg absorbреализуется путем отслеживания истории строк: это принципиально отличается от подхода, принятого hg histeditили git rebase, который, как правило, полагается на стратегии слияния, основанные на трехстороннем слиянии, для получения новой версии файла при множественном вводе. версии.

Этот подход в сочетании с тем фактом, что hg abs пропускает изменения при неоднозначном коммите приложения, означает, что hg abs никогда не столкнется с конфликтами слияния!

Теперь вы можете подумать, что если игнорировать строки с неоднозначными целями приложения, патч всегда будет применяться чисто, используя классическое трехстороннее слияние. Это утверждение логически звучит правильно. Но это не так: hg absorbможно избежать конфликтов слияния, когда слияние выполняется hg histeditили не удается git rebase -i.

VonC
источник
0

Я думаю chistedit(встроенный с Mercurial 2.3) наиболее близок к rebase -iчистому Mercurial ( chisteditэто интерактивная версия histedit). Попав в histedit, foldкоманда сопоставляется с rebase, squashа rollкоманда - с rebase fixup. См. Документацию histedit для получения дополнительной информации.

Вот простой пример. Предположим, у вас есть следующее и вы хотите переместить все изменения 1e21c4b1 в предыдущую ревизию и просто сохранить сообщение предыдущей ревизии.

@  1e21c4b1 drees tip
|  A commit you want to squash
o  b4a738a4 drees
|  A commit
o  788aa028 drees
|  Older stuff

Вы можете запустить, hg chistedit -r b4a738a4чтобы отредактировать историю обратно на b4a738a4. В chistedit вы затем наведите курсор на 1e21c4b1 и нажмите, rчтобы указать, что вы хотите откатить эту ревизию. Обратите внимание, что порядок в histedit (от самого старого к самому новому) меняется на противоположный hg log( от самого нового к самому старому).

#0  pick   160:b4a738a49916   A commit
#1  ^roll  161:1e21c4b1500c

Выбрав свои изменения, вы затем cрешаете их зафиксировать. Результат следующий:

@ bfa4a3be drees tip | Сделка о 788aa028 drees | Старые вещи

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

Обратите внимание, чтобы использовать любого histeditили chisteditвам нужно добавить histeditк расширениям в файле ~ / .hgrc:

[extensions]
histedit =

Я предложил, chisteditпотому что он наиболее близок rebase -iи работает где-либо в истории. Если вы действительно хотите заменить / перенастроить текущую ревизию на предыдущую, тогда @G. Предложение Демеки stripможет быть хорошим, поскольку то, что происходит, ясно. Он встроен, начиная с Mercuria 2.8. Чтобы получить результаты, аналогичные приведенным выше, вы можете сделать следующее:

hg strip .
hg add
hg commit --amend

Обратите внимание strip, как и histedit, в вашем ~ / .hgrc необходимо включить:

[extensions]
strip =
Studgeek
источник
0

Предположим, вы хотите объединить 2 последних коммита.

  1. Найдите номер редакции

    hg log -G -l 3
    

    возможный выход:

    @  changeset:   156:a922d923cf6f
    |  branch:      default
    |  tag:         tip
    |  user:        naXa!
    |  date:        Thu Dec 13 15:45:58 2018 +0300
    |  summary:     commit message 3
    |
    o  changeset:   155:5feb73422486
    |  branch:      default
    |  user:        naXa!
    |  date:        Thu Dec 13 15:22:15 2018 +0300
    |  summary:     commit message 2
    |
    o  changeset:   154:2e490482bd75
    |  branch:      default
    ~  user:        naXa!
       date:        Thu Dec 13 03:28:27 2018 +0300
       summary:     commit message 1
    
  2. Ветка с мягким сбросом

    hg strip --keep -r 155
    
  3. Зафиксируйте изменения снова

    hg commit -m "new commit message"
    

Ноты

stripтребует включения встроенного расширения. Создайте / отредактируйте ~/.hgrcфайл конфигурации со следующим содержанием:

[extensions]
strip = 
naXa
источник
-1

Я использую:

hg phase --draft --force -r 267
...
hg rebase --dest 282 --source 267 --collapse
саша-ч
источник