Какой самый простой способ совершить и нажать один файл, оставив другие модификации в одиночку?

Я относительно новичок в 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, так как когда я отправляю его в другой репозиторий, если в нем есть изменения, которые я не выполнил, он хочет, чтобы я вытащил их, объединил их и передал это слияние в хранилище. Коммиты после слияния не позволяют вам пропустить файлы, поэтому он заставляет вас фиксировать все в вашем локальном хранилище.

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

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

Ответ 1

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

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

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


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

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

Получите это с:

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

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

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

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py

Ответ 2

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

hg commit -m "commit message" filename

Затем просто нажмите.

hg push

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

hg push --rev .

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

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

Ответ 3

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

$ 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

На этом этапе вы вытеснили миграцию, сохранив другие локальные изменения. Другие изменения находятся в патче в очереди. Я делаю большую часть своего личного развития, используя очередь патчей, чтобы помочь мне лучше структурировать мои изменения. Если вы хотите избавиться от очереди исправлений и вернуться к нормальному стилю, вам придется экспортировать свои изменения и reimport их в "нормальный" 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.

Ответ 4

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

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

Ответ 5

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

 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 для автоматического внесения изменений.

Ответ 6

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

И затем просто hg push, чтобы нажать вновь созданную фиксацию.

Я поставил более подробную информацию об использовании hg commit --interactive в этом ответе: fooobar.com/info/59591/...