Какой самый простой способ совершить и нажать один файл, оставив другие модификации в одиночку?
Я относительно новичок в 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/...