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

StackOverflow https://stackoverflow.com/questions/125272

Вопрос

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

Это было полезно?

Решение

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

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

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


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

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

Получите это с помощью:

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

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

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

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

Другие советы

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

hg commit -m "commit message" filename

Затем просто вытолкнись наружу.

hg push

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

hg push --rev .

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

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

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.

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top