Какой самый простой способ зафиксировать и отправить один файл, оставив другие модификации без изменений? - PullRequest
72 голосов
/ 24 сентября 2008

Я относительно новичок в Mercurial, и моя команда сейчас пробует его как замену Subversion.

Как я могу зафиксировать и отправить один файл в другой репозиторий, оставив другие изменения в моем рабочем каталоге незафиксированными (или, по крайней мере, не перенесенные в другой репозиторий)?

Это происходит для нас с миграцией базы данных. Мы хотим передать миграцию в систему контроля версий, чтобы администратор базы данных мог просматривать и редактировать ее, пока мы работаем над изменениями кода, чтобы выполнить миграцию этой базы данных. Изменения еще не готовы, поэтому мы не хотим выталкивать их всех.

В Subversion я бы просто сделал:

svn add my_migration.sql  
# commit only the migration, but not the other files I'm working on
svn commit -m "migration notes" my_mygration.sql

и продолжайте работать локально.

Это не работает с Mercurial, как когда я отправляю его в другой репозиторий, если в нем есть изменения, которые я не выполнил, он хочет, чтобы я их спустил, слил и зафиксировал которые сливаются с хранилищем. Коммиты после слияния не позволяют вам пропустить файлы, поэтому он заставляет вас фиксировать все в вашем локальном хранилище.

Самая простая вещь, которую я могу выяснить, это зафиксировать файл в моем локальном репозитории, клонировать мой локальный репозиторий, извлечь любые новые изменения из реального репозитория, объединить их и зафиксировать это объединение, и они вытолкнут мои изменения. 1014 *

hg add my_migration.sql 
hg commit -m "migration notes" my_migration.sql 
cd ..
hg clone project project-clone
cd project-clone
hg fetch http://hg/project
hg push  http://hg/project

Это работает, но мне кажется, что я упускаю что-то более простое, какой-то способ сказать Mercurial игнорировать файлы, уже находящиеся в моем рабочем каталоге, просто выполнить слияние и отправить файлы вместе. Я подозреваю, что ртутные очереди могут сделать это, но я еще не до конца понимаю mq.

Ответы [ 6 ]

39 голосов
/ 13 июля 2010

Прошло почти 2 года с тех пор, как я изначально задал этот вопрос. Я бы сделал это по-другому (как я уже упоминал в комментарии над вопросом выше). Теперь я бы вместо этого зафиксировал мои изменения в одном файле в моем локальном репозитории (вы можете использовать расширение hg record, чтобы фиксировать только фрагменты файла):

hg commit -m "commit message" filename

Тогда просто вытолкни.

hg push

Если есть конфликт, потому что в репо были внесены другие изменения, которые мне нужно слить в первую очередь, я бы обновил до родительской ревизии (замечено с "hg parent -r.", Если вы не знаете, что это такое ), внесите мои другие изменения, чтобы у меня было 2 головы. Затем вернитесь к исходному файлу фиксации и внесите изменения в эту версию. Затем вытолкните изменения с помощью

hg push --rev .

Чтобы вытолкнуть только один файл и объединить эту ревизию. Затем вы можете объединить две головы, которые у вас есть на месте.

Таким образом, вы избавляетесь от mq-содержимого и потенциальных отклонений, а также отслеживает все с помощью контроля источников. Вы также можете отключить ревизии hg strip, если позже решите, что они вам не нужны.

31 голосов
/ 24 сентября 2008

Существует функция Mercurial, которая реализует команды полок и полок, что дает вам интерактивный способ указать изменения, которые нужно сохранить до более позднего времени: Полка .

Тогда вы можете hg shelve и hg unshelve, чтобы временно сохранить изменения. Это позволяет вам работать на уровне «заплатки», чтобы выбрать и отложить предметы на полку. Похоже, он не отложил файл в списке для добавления, только файлы, уже находящиеся в репо с изменениями.

Он включен в Mercurial как «расширение», которое означает, что вы должны включить его в своем конфигурационном файле hg.


Примечания для действительно старых версий Mercurial (до включения полки - в этом больше нет необходимости):

Я не видел каких-либо замечательных инструкций по установке с некоторым поиском в Google, поэтому вот объединенный материал, который я использовал, чтобы заставить его работать:

Получить с:

hg clone http://freehg.org/u/tksoh/hgshelve/ hgshelve

Единственный файл (в настоящее время) в проекте - это файл hgshelve.py.

Измените ~ / .hgrc, чтобы добавить расширение полки, указывающее, где вы клонировали репо:

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py
10 голосов
/ 20 февраля 2009

tl; dr: Мое оригинальное объяснение выглядит сложным, но я надеюсь, что оно полностью объясняет, как использовать очередь патчей. Вот короткая версия:

$ hg qnew -m "migration notes" -f migration my_migration.sql
$ hg qnew -f working-code
# make some changes to your code
$ hg qrefresh # update the patch with the changes you just made
$ hg qfinish -a # turn all the applied patches into normal hg commits

Mercurial Queues делает подобные вещи легкими и делает возможными более сложные манипуляции с наборами изменений. Это стоит учиться.

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

# create a patch called migration containing your migration
$ hg qnew -m "migration notes" -f migration.patch my_migration.sql
$ hg qseries -v # the current state of the patch queue, A means applied
0 A migration.patch
$ hg qnew -f working-code.patch # put the rest of the code in a patch
$ hg qseries -v
0 A migration.patch
1 A working-code.patch

Теперь давайте поработаем над рабочим кодом. Я собираюсь продолжать делать qseries, просто чтобы быть в явном виде, но как только вы создадите мысленную модель очередей патчей, вам не придется продолжать просматривать список.

$ hg qtop # show the patch we're currently editing
working-code.patch
$ ...hack, hack, hack...
$ hg diff # show the changes that have not been incorporated into the patch
blah, blah
$ hg qrefresh # update the patch with the changes you just made
$ hg qdiff # show the top patch's diff

Поскольку вся ваша работа теперь сохраняется в очереди исправлений, вы можете отменить эти изменения и восстановить их после того, как вы извлекли удаленные изменения. Обычно, чтобы отменить все исправления, просто сделайте hg qpop -a. Просто чтобы показать эффект на очередь патчей, я выкину их по одному за раз.

$ hg qpop # unapply the top patch, U means unapplied
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qtop
migration.patch
$ hg qpop
$ hg qseries -v
0 U migration.patch
1 U working-code.patch

На данный момент в вашем каталоге нет изменений. Сделайте hg fetch. Теперь вы можете включить изменения очереди исправлений и объединить их, если возникнут конфликты. Концептуально это немного похоже на ребаз git.

$ hg qpush # put the first patch back on
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qfinish -a # turn all the applied patches into normal hg commits
$ hg qseries -v
0 U working-code.patch
$ hg out
migration.patch commit info... blah, blah
$ hg push # push out your changes

На данный момент вы вытеснили миграцию, сохранив другие локальные изменения. Ваши другие изменения находятся в патче в очереди. Я делаю большую часть своей личной разработки, используя очередь патчей, чтобы помочь мне лучше структурировать свои изменения. Если вы хотите избавиться от очереди исправлений и вернуться к обычному стилю, вам придется экспортировать свои изменения и повторно импортировать их в «обычный» Mercurial.

$ hg qpush
$ hg qseries -v
0 A working-code.patch
$ hg export qtip > temp.diff
$ rm -r .hg/patches # get rid of mq from the repository entirely
$ hg import --no-commit temp.diff # apply the changes to the working directory
$ rm temp.diff

Я очень зависим от очередей исправлений для разработки, и mq - одна из самых хороших реализаций. Возможность создания нескольких изменений одновременно действительно улучшает сфокусированность и чистоту ваших коммитов. Требуется некоторое время, чтобы привыкнуть, но он невероятно хорошо сочетается с рабочим процессом DVCS.

3 голосов
/ 10 октября 2008

Другой вариант, если вы не хотите полагаться на расширения, - это локально сохранить клон вашего вышестоящего репозитория, который вы используете только для таких задач интеграции.

В вашем примере вы можете просто вытащить / объединить свое изменение с репозиторием интеграции / апстрима и отправить его прямо на удаленный сервер.

2 голосов
/ 04 февраля 2015

Обычно я использую для фиксации одного файла:

 hg commit -m "commit message" filename

В случае, если у меня возникнет конфликт слияния, и я все еще не готов принять изменения, выполните следующие действия:

1) Создать файл патча.

hg diff > changes.patch

2) Отменить все оставшиеся незафиксированные изменения, только после проверки файла исправления.

hg revert --all

3) Извлечь, обновить и объединить до последней ревизии

hg pull -u
hg merge
hg commit -m "local merge"

4) Теперь просто импортируйте ваш патч обратно и получите изменения.

hg import --no-commit changes.patch

Не забудьте использовать флаг -no-commit для автоматической фиксации изменений.

1 голос
/ 21 декабря 2017

Поскольку вы сказали, что проще всего, я часто использую hg commit -i (--interactive) даже при фиксации целых файлов. С --interactive вы можете просто выбрать нужные файлы, а не вводить их полный путь в командной строке. В качестве дополнительного бонуса вы можете даже выборочно включать / исключать фрагменты в файлах.

А затем просто hg push, чтобы отправить этот вновь созданный коммит.

Я добавлю более подробную информацию об использовании hg commit --interactive в этом ответе: https://stackoverflow.com/a/47931672/255961

...