Як за допомогою Mercurial я можу “стиснути” серію наборів змін в один перед натисканням?


96

Скажімо, у мене є локальне та віддалене сховище Mercurial. Тепер я починаю працювати над функцією. Я працюю над цим, і коли я думаю, що це зроблено, я фіксую набір змін. Перевіривши його ще трохи, я переконався, що я міг би ще більше вдосконалити цю функцію, змінивши щось у коді. Я вношу зміни та зобов’язуюсь. Через 20 хвилин я виявляю помилку в цій новій функції, тому виправляю це і фіксую це теж.

Зараз у мене є 3 набори змін, які я б дуже хотів передати у віддалене сховище як один набір змін із повідомленням "Впровадження функції X", наприклад.

Як я можу це зробити без особливих клопотів? Я вважаю, що міг би це зробити за допомогою латок, але це, здається, багато роботи.


40
Очевидно, що це не моє місце, щоб відмовляти вас від спроб стиснути ваші набори змін, але, можливо, ви захочете врахувати, що половина значення контролю версій відповідає "чому", а не лише "що" через місяці та роки. Точне подання того, як з’явилася функція, і на яких етапах, може мати майбутнє значення. Викидати це здається таким ... неконтрольованим контролем.
Ry4an Brase

Це призводить до іншого питання ... Яка різниця між "histedit" та "крахом"
sylvanaar

1
колапс забезпечує підмножину функцій histedit, а histedit має набагато інтуїтивнішу UX.
Стефан Русек,

1
Він також надає механізм редагування об'єднаного повідомлення про набір змін.
Стефан Русек,

1
@ Ry4an: Насправді, стиснення / згортання додає актуальності контролю версій у деяких випадках. Без стиснення я мав би два коміти щодня, які не мали нічого спільного з функціями чи виправленнями помилок, а стосувалися переміщення коду з ноутбука на робочий стіл і навпаки. Вони просто додають шуму в історію версій.
Джон Рейнольдс,

Відповіді:


39

20
Привіт з майбутнього! Я просто погуглив за ту саму функціональність, і, мабуть, сьогодні hg підтримує це нестандартно hg rebase --collapse. Перевірте вікі hg за командою rebase. Оскільки це запитання є 3-м загальним результатом пошуку та першим щодо stackoverflow, я вважав, що інформація може бути корисною.
a.peganz,

1
Вітаємо ще далі в майбутньому !! Здається, розширення перебазування націлено виключно на переміщення наборів змін з однієї гілки на іншу. Так, є параметр --collapse, але, як видається, він застосовується лише при переміщенні набору змін по гілках. Див. < Mercurial-scm.org/wiki/… >
Бред Естріхер

3
Ви можете використовувати hg rebaseв --collapseмежах однієї гілки.
UuDdLrLrS

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а потім робить все в одному коміті?
Г. Demecki

@ G.Demecki, оскільки це потенційно дуже збиткова операція ..? Хоча MQ є надмірним (і навіть часто не рекомендується), за винятком випадків, коли потрібно такий робочий процес.
користувач2864740

@ user2864740 Ви можете мати рацію, бо я не експерт з Меркурія. Але за замовчуванням hg stripрозмістить резервну копію в .hg/strip-backup/каталозі. Думаю, це не настільки безпечно, git reflogале все ж забезпечує якийсь порятунок.
Г. Демецький

19

Якщо ви використовуєте TortoiseHg, use може просто вибрати дві версії (за допомогою 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, але він не виходить з ладу .. принаймні новіші версії залишать вас на тимчасовій гілці, якщо щось піде жахливо, тому єдиний раз, коли набори змін будуть видалені - після того, як буде зафіксовано нову гілку.
користувач2864740

2

Я ніколи не використовував Mercurial, але це дуже схоже на те, про що Мартін Фаулер говорив у своєму блозі не так давно:

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


Це виглядає більш ніж дещо складно, але дякую за посилання. Чесно кажучи, я сподіваюся на якесь магічне продовження, яке зробить саме те, що я хочу, як забирати та пересаджувати за допомогою витягування та збору вишні.
Лукас

0

Чому не просто hg strip --keepкомандувати?

Тоді ви можете фіксувати всі зміни як один коміт.


@Strawberry не дає відповіді ?? На його думку, це чудово відповідає на авторське запитання. Ви можете пояснити свою думку?
Г. Демецький

Це давня історія, тому я відкину це зауваження - але затверджена відповідь здається більш авторитетним посиланням.
Полуниця

1
@Strawberry Справді, це давня нитка. Але прийнята відповідь застаріла, оскільки Mercurial більше не потребує окремого розширення третьої сторони для цієї роботи.
Г. Демецький

0

HistEdit зробить те, що ви хочете, але це, мабуть, надмірно. Якщо єдине, що вам потрібно, це скласти деякі набори змін разом, Згорнути розширення зробить цю роботу.


1
хоча він надає набагато простіший у використанні та розумінні інтерфейс, що є більш ніж достатньою підставою для його використання, але він також забезпечує механізм редагування злитого повідомлення про набір змін, що є іншою справою, яку я завжди хочу робити, коли об'єднати набори змін.
Стефан Русек,

І проблема лише розуміння користувацького інтерфейсу насправді не зрозуміла .. У будь-якому разі, коли минуле histedit дозволяє змінювати "помилки", а також змінювати повідомлення під час "складання". Гістедит ідеальний; якщо що, продовження згортання мало корисне.
користувач2864740

0

Припустимо, у вас є два неопублікованих THISі THATфіксує в Mercurial і сподобається їм, щоб вони об’єдналися в єдиний коміт в THISточці ::

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

Переконайтеся, що ваші коміти не публікуються:

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

Оновлення до LASTкоміту ::

$ hg up

та імпортує зобов’язання до THISMQ ::

$ 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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.