Как управлять параллельной разработкой с Mercurial?
Это вопрос наилучшей практики, и я ожидаю, что ответ будет "это зависит". Я просто надеюсь узнать больше реальных сценариев и рабочих процессов.
Прежде всего, я говорю о разных изменениях для одного и того же проекта.
Допустим, у вас есть база кода в репозитории hg. Вы начинаете работать над сложной новой функцией A, а ваш надежный тестировщик сообщает о сложной ошибке B (у вас есть тестеры, верно?).
Это тривиально, если (исправление) B зависит от A. Вы просто ci A, затем c B.
У меня вопрос, что делать, когда они независимы (или, по крайней мере, кажется сейчас).
Я могу думать о следующих способах:
- Используйте отдельный клон для B.
- Используйте анонимные или именованные ветви или закладки в одном и том же хранилище.
- Используйте MQ (с патчем B на вершине A).
- Используйте разветвленный MQ (я объясню позже).
- Используйте несколько MQ (начиная с 1.6)
1 и 2 освещены в превосходном блоге @Steve Losh со ссылкой на слегка связанный вопрос.
Одним огромным преимуществом 1 по сравнению с другими вариантами является то, что он не требует какой-либо перестройки, когда вы переключаетесь с работы над одной вещью на другую, потому что файлы физически разделены и независимы. Так что это действительно единственный выбор, если, например, A и / или B касаются заголовочного файла, который определяет логическое состояние с тремя состояниями и включается в тысячи файлов C (не говорите мне, что вы не видели такой устаревший код база).
3, вероятно, самый простой (с точки зрения настройки и издержек), и вы можете изменить порядок A и B, если B - небольшое и / или срочное исправление. Однако это может быть сложно, если A и B касаются одного и того же файла (ов). Легко исправить фрагменты патчей, которые не удалось применить, если изменения A и B ортогональны в одном и том же файле (ах), но концептуально это все еще немного рискованно.
4 может вызвать у вас головокружение, но это самый мощный, гибкий и масштабируемый способ. Я по умолчанию hg qinit
с -c
так как я хочу пометить исправления в процессе работы и протолкнуть их, но это требует концептуального скачка, чтобы понять, что вы также можете переходить в MQ-репо. Вот шаги (mq = hg --mq):
hg qnew bugA
; внести изменения для A;hg qref
mq branch branchA; hg qci
hg qpop; mq up -rtip^
hg qnew bugB
; внести изменения для B;hg qref
mq branch branchB; hg qci
- Чтобы снова поработать над А:
hg qpop; mq up branchA; hg qpush
Кажется сумасшедшим делать столько шагов, и всякий раз, когда вам нужно сменить работу, вы должны hg qci; hg qpop; mq up <branch>; hg qpush
, Но учтите следующее: у вас есть несколько именованных веток релиза в одном и том же хранилище, и вам нужно одновременно работать над несколькими проектами и исправлять ошибки для всех из них (вам лучше получить гарантированный бонус за этот вид работы). Вы очень скоро потеряетесь с другими подходами.
Теперь мои друзья-любители HG, есть ли другие / лучшие альтернативы?
(ОБНОВИТЬ) qqueue
почти делает № 4 устаревшим. Смотрите элегантное описание Стива Лоша здесь.
3 ответа
Кажется, что нет больше или лучше, чем те, которые я перечислил в вопросе. И вот они снова.
- Используйте один клон на проект.
- Плюсы: полное разделение, поэтому нет необходимости перестраивать при переключении проектов.
- Минусы: цепочка инструментов должна переключаться между двумя клонами.
- Используйте анонимные или именованные ветви или закладки в одном и том же хранилище.
- Плюсы: стандартная практика hg (или любая DVCS); чисто и понятно.
- Минусы: необходимо зафиксировать перед переключением и восстановить после.
- Используйте MQ с одним патчем (или несколькими последовательными патчами) на проект.
- Плюсы: просто и легко.
- Минусы: должны
qrefresh
до переключения и перестроить после; сложно и рискованно, если проекты не являются ортогональными.
- Используйте одну ветку MQ (или
qqueue
в 1.6+) за проект.- Плюсы: сверхгибкий и масштабируемый (для количества одновременных проектов)
- Минусы: должны
qrefresh
а такжеqcommit
до переключения и перестроить после; чувствует себя сложным.
Как и всегда, серебряной пули нет, поэтому выбирайте подходящую для работы.
(ОБНОВЛЕНИЕ) Для всех, кто влюблен в MQ, использование MQ поверх обычных веток (#2 + #3), вероятно, является наиболее распространенной и предпочтительной практикой.
Если у вас есть два параллельных проекта с базовым уровнем в двух ветвях (например, следующий выпуск и текущий выпуск), переходить между ними тривиально:
hg qnew; {coding}; hg qrefresh; {repeat}
hg qfinish -a
hg update -r <branch/bookmark/rev>
hg qimport -r <rev>; {repeat}
Для последнего шага qimport
следует добавить -a
возможность импортировать строку наборов изменений сразу. Я надеюсь, что Martin Geisler это заметит:)
Я бы всегда использовал именованные ветви, потому что это позволяет Mercurial выполнять свою работу: сохранять историю вашего проекта и помнить, почему вы сделали какие изменения в каком порядке в вашем исходном коде. Независимо от того, сидеть ли на вашем диске один или два клона, как правило, легко, учитывая мой стиль работы, по крайней мере:
У вашего проекта нет процесса сборки, чтобы вы могли тестировать и запускать программы прямо из исходного кода? Тогда у меня будет соблазн иметь только одного клона, и
hg up
туда и обратно, когда мне нужно работать на другую ветку.Но если у вас есть buildout, virtualenv или другая структура, которая создается и которая может расходиться между двумя ветвями, тогда выполните
hg up
тогда ожидание повторного запуска процесса сборки может быть большой болью, особенно если речь идет о настройке примера базы данных. В этом случае я бы определенно использовал два клона, один сидящий на кончике ствола, а другой сидящий на кончике ветки аварийных функций.
Таким образом, вопрос в том, когда вам говорят прекратить работу над функцией A и начать независимую функцию B, какие существуют альтернативные варианты, для: Как управлять параллельной разработкой с Mercurial?
Давайте посмотрим на проблему с удаленным параллелизмом, так же, как вы пишете многопоточный код - определите простой рабочий процесс для решения любой заданной вам проблемы и примените его к каждой проблеме. Mercurial присоединится к работе, как только это будет сделано. Таким образом, программист A будет работать над функцией A. Программист B будет работать над функцией B. И то, и другое случается с вами. (Если бы у нас был многоядерный мозг:)
Я бы всегда использовал именованные ветви, потому что это позволяет Mercurial выполнять свою работу: сохранять историю вашего проекта и помнить, почему вы сделали какие изменения в каком порядке в вашем исходном коде.
Я согласен с мнением Брэндона, но мне интересно, не заметил ли он, что функция А не была протестирована? В худшем случае код компилируется и проходит модульные тесты, но некоторые методы реализуют предыдущие требования, а некоторые методы реализуют новые. Разница с предыдущей регистрацией - это инструмент, который я бы использовал, чтобы помочь мне вернуться на путь с функцией А.
Является ли ваш код для функции A в тот момент, когда вы обычно проверяете его? Переключение с функции A на работу с функцией B не является причиной для передачи кода руководителю или ветви. Только проверяйте код, который компилирует и проходит ваши тесты. Моя причина в том, что если программисту C нужно запустить функцию C, новая проверка этой ветви больше не является лучшим местом для начала. Поддержание работоспособности ваших веток означает, что вы можете быстро реагировать и исправлять ошибки.
Цель состоит в том, чтобы ваш (проверенный и проверенный) код работал, поэтому вы хотите, чтобы весь ваш код в конечном итоге сливался с головой (ваших ветвей разработки и предыдущих версий). Суть в том, что я видел, что ветвление используется неэффективно: код становится устаревшим, а затем не используется, объединение становится сложнее, чем исходная проблема.
Только ваш вариант 1 имеет смысл для меня. В общем:
- Вы должны думать, что ваш код работает, прежде чем кто-то другой увидит его.
- Пользуйся головой над веткой.
- Отделение и регистрация, если кто-то еще поднимает проблему.
- Филиал, если вашей автоматизированной системе или тестерам нужен только ваш код.
- Филиал, если вы являетесь частью команды, работающей над проблемой. Считайте это головой, см. 1-4.
За исключением файлов конфигурации, процессы сборки должны быть проверкой и одной командой сборки. Переключение между клонами должно быть не более сложным, чем присоединение к проекту нового программиста. (Я признаю, что мой проект нуждается в некоторой работе здесь.)