Как управлять параллельной разработкой с Mercurial?

Это вопрос наилучшей практики, и я ожидаю, что ответ будет "это зависит". Я просто надеюсь узнать больше реальных сценариев и рабочих процессов.

Прежде всего, я говорю о разных изменениях для одного и того же проекта.

Допустим, у вас есть база кода в репозитории hg. Вы начинаете работать над сложной новой функцией A, а ваш надежный тестировщик сообщает о сложной ошибке B (у вас есть тестеры, верно?).

Это тривиально, если (исправление) B зависит от A. Вы просто ci A, затем c B.

У меня вопрос, что делать, когда они независимы (или, по крайней мере, кажется сейчас).

Я могу думать о следующих способах:

  1. Используйте отдельный клон для B.
  2. Используйте анонимные или именованные ветви или закладки в одном и том же хранилище.
  3. Используйте MQ (с патчем B на вершине A).
  4. Используйте разветвленный MQ (я объясню позже).
  5. Используйте несколько 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):

  1. hg qnew bugA; внести изменения для A; hg qref
  2. mq branch branchA; hg qci
  3. hg qpop; mq up -rtip^
  4. hg qnew bugB; внести изменения для B; hg qref
  5. mq branch branchB; hg qci
  6. Чтобы снова поработать над А: hg qpop; mq up branchA; hg qpush

Кажется сумасшедшим делать столько шагов, и всякий раз, когда вам нужно сменить работу, вы должны hg qci; hg qpop; mq up <branch>; hg qpush, Но учтите следующее: у вас есть несколько именованных веток релиза в одном и том же хранилище, и вам нужно одновременно работать над несколькими проектами и исправлять ошибки для всех из них (вам лучше получить гарантированный бонус за этот вид работы). Вы очень скоро потеряетесь с другими подходами.

Теперь мои друзья-любители HG, есть ли другие / лучшие альтернативы?


(ОБНОВИТЬ) qqueue почти делает № 4 устаревшим. Смотрите элегантное описание Стива Лоша здесь.

3 ответа

Решение

Кажется, что нет больше или лучше, чем те, которые я перечислил в вопросе. И вот они снова.

  1. Используйте один клон на проект.
    • Плюсы: полное разделение, поэтому нет необходимости перестраивать при переключении проектов.
    • Минусы: цепочка инструментов должна переключаться между двумя клонами.
  2. Используйте анонимные или именованные ветви или закладки в одном и том же хранилище.
    • Плюсы: стандартная практика hg (или любая DVCS); чисто и понятно.
    • Минусы: необходимо зафиксировать перед переключением и восстановить после.
  3. Используйте MQ с одним патчем (или несколькими последовательными патчами) на проект.
    • Плюсы: просто и легко.
    • Минусы: должны qrefresh до переключения и перестроить после; сложно и рискованно, если проекты не являются ортогональными.
  4. Используйте одну ветку 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 выполнять свою работу: сохранять историю вашего проекта и помнить, почему вы сделали какие изменения в каком порядке в вашем исходном коде. Независимо от того, сидеть ли на вашем диске один или два клона, как правило, легко, учитывая мой стиль работы, по крайней мере:

  1. У вашего проекта нет процесса сборки, чтобы вы могли тестировать и запускать программы прямо из исходного кода? Тогда у меня будет соблазн иметь только одного клона, и hg up туда и обратно, когда мне нужно работать на другую ветку.

  2. Но если у вас есть buildout, virtualenv или другая структура, которая создается и которая может расходиться между двумя ветвями, тогда выполните hg up тогда ожидание повторного запуска процесса сборки может быть большой болью, особенно если речь идет о настройке примера базы данных. В этом случае я бы определенно использовал два клона, один сидящий на кончике ствола, а другой сидящий на кончике ветки аварийных функций.

Таким образом, вопрос в том, когда вам говорят прекратить работу над функцией A и начать независимую функцию B, какие существуют альтернативные варианты, для: Как управлять параллельной разработкой с Mercurial?

Давайте посмотрим на проблему с удаленным параллелизмом, так же, как вы пишете многопоточный код - определите простой рабочий процесс для решения любой заданной вам проблемы и примените его к каждой проблеме. Mercurial присоединится к работе, как только это будет сделано. Таким образом, программист A будет работать над функцией A. Программист B будет работать над функцией B. И то, и другое случается с вами. (Если бы у нас был многоядерный мозг:)

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

Я согласен с мнением Брэндона, но мне интересно, не заметил ли он, что функция А не была протестирована? В худшем случае код компилируется и проходит модульные тесты, но некоторые методы реализуют предыдущие требования, а некоторые методы реализуют новые. Разница с предыдущей регистрацией - это инструмент, который я бы использовал, чтобы помочь мне вернуться на путь с функцией А.

Является ли ваш код для функции A в тот момент, когда вы обычно проверяете его? Переключение с функции A на работу с функцией B не является причиной для передачи кода руководителю или ветви. Только проверяйте код, который компилирует и проходит ваши тесты. Моя причина в том, что если программисту C нужно запустить функцию C, новая проверка этой ветви больше не является лучшим местом для начала. Поддержание работоспособности ваших веток означает, что вы можете быстро реагировать и исправлять ошибки.

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

Только ваш вариант 1 имеет смысл для меня. В общем:

  1. Вы должны думать, что ваш код работает, прежде чем кто-то другой увидит его.
  2. Пользуйся головой над веткой.
  3. Отделение и регистрация, если кто-то еще поднимает проблему.
  4. Филиал, если вашей автоматизированной системе или тестерам нужен только ваш код.
  5. Филиал, если вы являетесь частью команды, работающей над проблемой. Считайте это головой, см. 1-4.

За исключением файлов конфигурации, процессы сборки должны быть проверкой и одной командой сборки. Переключение между клонами должно быть не более сложным, чем присоединение к проекту нового программиста. (Я признаю, что мой проект нуждается в некоторой работе здесь.)

Другие вопросы по тегам