Mercurial: як внести зміни до останнього зобов'язання?


211

Я шукаю зустрічну частину git commit --amendв Mercurial, тобто спосіб змінити комісію, з якою пов'язана моя робоча копія. Мене цікавить лише останнє зобов'язання, а не довільне попереднє зобов'язання.

Вимоги до цієї процедури поправок:

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

  • якщо зобов’язання щодо внесення змін є одним із керівників моєї нинішньої гілки, не слід створювати нового керівника . Якщо фіксація не є головою, може бути створена нова голова.

  • процедура повинна бути безпечною таким чином, що якщо з якихось причин виправлення не вдасться, я хочу відновити таку ж робочу копію та стан сховища, що і до внесення змін. Іншими словами, якщо сама поправка може вийти з ладу, повинна бути встановлена ​​безпечна процедура відновлення робочої копії та стану сховища. Я маю на увазі "збої", які лежать в характері процедури внесення змін (наприклад, конфлікти), а не на проблеми, пов'язані з файловою системою (наприклад, обмеження доступу, неможливість блокування файлу для запису, ... )

Оновлення (1):

  • процедура повинна бути автоматизованою , тому її може виконувати клієнт GUI без будь-якої взаємодії з користувачем.

Оновлення (2):

  • Файли в робочому каталозі не повинні торкатися (можуть бути заблоковані файлові системи на певних модифікованих файлах). Це особливо означає, що можливий підхід ні в якому разі не вимагає чистого робочого каталогу.

Відповіді:


289

З випуском Mercurial 2.2 ви можете скористатися --amendопцією з hg commitдля оновлення останньої комісії з поточної робочої директорії

З посилання на командний рядок :

Прапор --amend може використовуватися для внесення змін до батьківського списку робочого каталогу з новим комітетом, який містить зміни в батьківському на додаток до тих, що в даний час повідомляються за статусом hg, якщо такі є. Стара фіксація зберігається в пакеті резервного копіювання в .hg / strip-backup (див. Довідку hg-довідки та hg довідки про розв’язування щодо її відновлення).

Повідомлення, користувач та дата беруться із зміненої комісії, якщо не зазначено. Якщо повідомлення не вказано в командному рядку, редактор відкриється із повідомленням зміненого комітету.

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


2
Хороша відповідь! Експериментальне розширення evolve дозволяє безпечно вносити зміни до невідповідних зобов'язань. Стара фіксація буде позначена застарілою та прихованою. З сервером, що не публікує, ви можете це зробити безпечно навіть після натискання наборів змін.
Мартін Гейслер

5
Щойно оновити повідомлення про останню фіксацію: hg commit --amend -m "це моє нове повідомлення"
Jay Sheth

52

У вас є три варіанти редагування комітетів у Mercurial:

  1. hg strip --keep --rev -1скасуйте останнє (1) фіксацію, щоб ви могли це зробити ще раз (див. цю відповідь для отримання додаткової інформації).

  2. Використання розширення MQ , яке постачається разом з Mercurial

  3. Навіть якщо він не постачається разом з Mercurial, варто згадати розширення Histedit

Ви також можете подивитися на сторінці « Історія редагування» вікі Mercurial.

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

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


1
Я не впевнений, чому я пропустив відкат, але, здається, роблю (майже) те, що хочу. Єдина проблема полягає в тому, що коли файл було видалено для мого оригіналу і він був відновлений для моєї поправки: перед відкатом він буде неперервано, після відкату буде заплановано видалення (але файл все ще існує в робочий каталог)
mstrap

@Marc Я не впевнений, що я розумію твою проблему, але подивись на команду забути, я думаю, це те, що ти шукаєш.
кртек

Я не думаю, що "забути" тут буде корисно. Ось проблема більш докладно: (1) Я переглядаю версію 2 (2) Видаліть "файл" та внесете деякі інші зміни (3) Внесіть зміни, в результаті чого перегляньте 3 (4) Тепер я передумаю та вирішу "файл" не слід видаляти з комісії, тому я хочу змінити редакцію 3. Отже, я знову додаю "файл", який зараз не змінюється (5) Тепер я виконую відкат: він скине dirstate та позначку " файл "як видалено. (6) При повторному виконанні "hg commit" файл "залишатиметься видаленим, хоча його більше не повинно бути. Як може виглядати автоматичне виправлення цього?
mstrap

1
Для автоматизованої частини я не знаю, але ви можете hg revert myfileскасувати видалення. Можливо, повторне додавання hg addдо файлу rollbackтакож працює.
кртек

3
Я погоджуюся, що слід уникати редагування опублікованих змін, але редагування моєї краєзнавчої історії є однією з важливих моментів DVCS. MQ з qimport - це чисте редагування історії, AFAICT.
mstrap

38

Еквівалент GUI для hg commit --amend:

Це також працює з GUI TortoiseHG (я використовую v2.5):

Перейдіть до подання «Зв’язати» або, переглянувши робочий стіл, виберіть запис «робочий каталог» Кнопка "Звернути" має опцію "Змінити поточну версію" (натисніть стрілку вниз, щоб знайти її).

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

          ||
          ||
          \/

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

Caveat emptor :

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

Натиснувши кнопку, виклик "присвоїти - змінити", щоб "змінити" редакцію.

Більше інформації про це на телеканалі THG dev


Дуже корисно, дякую. THG достатньо розумний, щоб за замовчуванням виконати повідомлення (внести зміни) до повідомлення попереднього вступу - саме те, що я хотів.
UuDdLrLrSs

7

Я налаштовуюсь на те, що написав krtek. Більш конкретно рішення 1:

Припущення:

  • Ви зробили один (!) набір змін, але ще не натиснули його
  • ви хочете змінити цей набір змін (наприклад, додати, видалити або змінити файли та / або повідомлення про фіксацію)

Рішення:

  • використовувати hg rollbackдля скасування останнього коміту
  • знову вступити в дію з новими змінами

Відкат дійсно скасовує останню операцію. Спосіб його роботи досить простий: звичайні операції в HG додаватимуться лише до файлів; сюди входить фіксація. Mercurial відслідковує довжину файлів останньої транзакції і тому може повністю скасувати один крок, обрізавши файли до їх старої довжини.


1
Дякую за налаштування рішення (1); з відкатом залишилася лише невелика проблема, будь ласка, дивіться мій коментар щодо рішення krtek.
mstrap

8
Одне, що слід наголосити на відкаті, оскільки це вигадує людей, це те, що це остання транзакція на репо, яка повертається назад, а не остання фіксація. Тож якщо щось інше спричинило запис у репо, відкат не допоможе. Це тонке, але важливе, що потрібно пам’ятати. MQ і histedit можуть допомогти після закриття вікна відката, але все ще лише до певного моменту.
Пол S

7

Якщо припустити, що ви ще не поширювали свої зміни, ось що ви можете зробити.

  • Додайте до свого .hgrc:

    [extensions]
    mq =
    
  • У вашому сховищі:

    hg qimport -r0:tip
    hg qpop -a
    

    Звичайно, не потрібно починати з нульової редакції або висувати всі патчі, для останнього достатньо лише одного pop ( hg qpop) (див. Нижче).

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

  • hg qpush -a; hg qfinish -a
  • видаліть .diffфайли (неприкладені патчі), які все ще знаходяться в .hg / патчі (у вашому випадку має бути один).

Якщо ви не хочете , щоб забрати все з вашого патча, ви можете редагувати його за допомогою 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.

Звичайно, ця процедура вкрай обережна і ризикована . Зробіть резервну копію всього, перш ніж це зробити!

Як сторона, я це робив мільйони разів у приватних сховищах.


Я також розглядав можливість використання mq-extension, однак це вимагає досить багатьох операцій, для яких деякі з них можуть вийти з ладу (наприклад, якщо задіяні бінарні файли). Крім того, редагування .hg / patch / series не буде прийнятним, оскільки цю процедуру слід використовувати в клієнтському інтерфейсі (я оновив вимоги вище)
mstrap

Гммм, вибачте, що це не для вас, у приватному сховищі це справді забиває дупу (із резервними копіями - я вже жирним пальцем знищив репліку з ним ^^). Досить здорово поєднувати патчі в один, перш ніж натискати на місцеві зміни, використовуючи hg qfold, btw
hochl

+1 за використання MQ, але я думаю, ви перебралися за борт. Він запитує лише про внесення змін до останнього зобов'язання. Крім того, що імпорт буде кинутий, як тільки він потрапить на злиття. 'qimport -r порада; <редагувати речі>; qrefresh -e; qfin -a 'зробить роботу (-e для редагування повідомлення про вчинення)
Paul S

правда, злиття - це проблема, я зазвичай пропускаю лише один патч і використовую hg import -r<prev>:tip. Піти немає ярлика для попередньої версії, як у підриві.
hochl

2

Останні версії Mercurial включають evolveрозширення, яке забезпечує hg amendкоманду. Це дозволяє вносити зміни до комісії без втрати історії попередніх змін у контролі версій.

hg змінити [OPTION] ... [FILE] ...

псевдоніми: оновити

комбінуйте набір змін із оновленнями та замініть його новим

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's 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розширення.


Повторне використання того ж повідомлення про фіксацію - приємна особливість!
mpen

1

Можливо, не вирішити всіх проблем у первісному запитанні, але оскільки це, здається, є фактичним повідомленням про те, як mercurial може внести зміни до попереднього зобов’язання, я додам 2 центи, варті інформації.

Якщо ви схожі на мене і хочете лише змінити попереднє повідомлення про фіксацію (виправити помилку помилки тощо), не додаючи жодних файлів, це спрацює

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

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

Функціонально це те саме, що git commit --amendколи немає файлів в індексі / стадії.


0

Іншим рішенням може бути використання uncommitкоманди для виключення конкретного файлу з поточної фіксації.

hg uncommit [file/directory]

Це дуже корисно, коли ви хочете зберегти поточну фіксацію та скасувати виділення деяких файлів з фіксації (особливо корисно для files/directoriesвидалених).

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