2009-05-20 4 views
130

В настоящее время мы используем подрывную деятельность на относительно большой базе кода. Каждый выпуск получает свою собственную ветку, и исправления выполняются в отношении соединительной линии и переносятся в ветви выпуска, используя svnmerge.pyMercurial: Именованные ветви против множественных репозиториев

Я считаю, что настало время перейти к лучшему контролю источника, и я некоторое время играл с Mercurial ,

Кажется, есть две школы, хотя при управлении такой структурой выпуска с использованием Mercurial. Либо каждый выпуск получает свое собственное репо, и исправления производятся против ветви выпуска и помещаются в основную ветку (и любые другие более поздние ветви выпуска). ИЛИ используя именованные ветви в одном хранилище (или несколько копий соответствия).

В любом случае кажется, что я могу использовать что-то вроде трансплантации для изменений cherrypick для включения в ветви релиза.

Прошу вас; Каковы относительные достоинства каждого подхода?

ответ

129

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

Это означает, что клоны отлично подходят для быстрых экспериментов, где вы не хотите записывать название ветки, а названные ветви хороши для длинных ветвей («1.x», «2.x» и т. Д.).

Обратите внимание, что в одном хранилище можно легко разместить несколько светлых ветвей в Mercurial. Такие ветви хранилища можно добавить в закладки, чтобы их можно было легко найти снова. Давайте предположим, что вы клонировали хранилище компании, когда он выглядел следующим образом:

[a] --- [b] 

Вы поредактируете и сделать [x] и [y]:

[a] --- [b] --- [x] --- [y] 

Mean в то время как кто-то ставит [c] и [d] в хранилище, так когда вы тянете, вы получите диаграмму истории:

 
      [x] --- [y] 
     /
[a] --- [b] --- [c] --- [d] 

Здесь есть две головы в си репозиторий. Ваша рабочая копия всегда будет отображать единый набор изменений, так называемый рабочий набор родительских копий. Проверьте это:

% hg parents 

Предположим, что оно сообщает [y]. Вы можете увидеть головы

% hg heads 

и это сообщит [y] и [d].Если вы хотите обновить свой репозиторий чистой проверки в [d], а затем просто сделать (заменить [d] с номером версии для [d]):

% hg update --clean [d] 

Вы тогда увидите, что hg parents отчет [d]. Это означает, что ваша следующая фиксация будет иметь [d] в качестве родителя. Таким образом, вы можете исправить ошибку, вы заметили, в главной ветви и создать [e] ревизию:

 
      [x] --- [y] 
     /
[a] --- [b] --- [c] --- [d] --- [e] 

Чтобы подтолкнуть [e] только ревизию, что вам нужно сделать

% hg push -r [e] 

где [e] набор изменений хэш. По умолчанию hg push будет просто сравнивать репозитории и видеть, что [x], [y] и [e] отсутствуют, но вы, возможно, не захотите разделить и [y].

Если багфикс также влияет, вы хотите, чтобы объединить его с особенностью отрасли:

% hg update [y] 
% hg merge 

Это оставит свой график репозитария глядя, как это:

 
      [x] --- [y] ----------- [z] 
     /     /
[a] --- [b] --- [c] --- [d] --- [e] 

где [z] является слияние между [y] и [e]. Вы также могли бы выбрать, чтобы бросить ветку в сторону:

% hg strip [x] 

Моя главная точка этой истории такова: один клон может легко представить несколько дорожек развития. Это всегда верно для «простого hg» без использования каких-либо расширений. Тем не менее, bookmarks extension. Это позволит вам назначать имена (закладки) для наборов изменений. В приведенном выше примере вам понадобится закладка на голове разработки и одна на головке вверх. Закладки могут быть толкнул и потянул с Mercurial 1.6 и стал встроенной функцией Mercurial 1.8.

Если бы вы решили сделать два клона, ваш клон развития выглядел бы, как это после того, как сделать [x] и [y]:

[a] --- [b] --- [x] --- [y] 

И вышестоящий клон будет содержать:

[a] --- [b] --- [c] --- [d] 

вас прямо сейчас обратите внимание на ошибку и исправьте ее. Здесь вам не нужно hg update, так как клон вверх готов к использованию.Вы допускаете и создать [e]:

[a] --- [b] --- [c] --- [d] --- [e] 

Чтобы включить устранении ошибки в вашем клоне развития вы тянете его там:

 
[a] --- [b] --- [x] --- [y] 
      \ 
      [c] --- [d] --- [e] 

и слияния:

 
[a] --- [b] --- [x] --- [y] --- [z] 
      \     /
      [c] --- [d] --- [e] 

График Мощь выглядит по-другому, но он имеет ту же структуру, и конечный результат тот же. Используя клоны, вы должны были сделать немного меньше умственной бухгалтерии.

Названные ветви на самом деле не пришли сюда, потому что они довольно необязательны. Сам Mercurial был разработан с использованием двух клонов в течение многих лет, прежде чем мы перешли на использование названных ветвей. Мы также поддерживаем филиал под названием «стабильный» в дополнение к ветке «default» и делаем наши выпуски на основе «стабильной» ветки. См. Страницу standard branching в wiki для описания рекомендуемого рабочего процесса.

+1

если набор изменений пришел от другого пользователя, который был бы записан, поэтому использование клонов ничего плохого. При нажатии новой функции часто неинтересно знать, что вы сделали это из отдельного репо. Существует также расширение localbranch, которое дает вам локальную ветку. Полезно, когда клонирование репо связано с высокими затратами (время/пространство). –

+2

, ссылаясь на: «клоны отлично подходят для быстрых экспериментов» - нет, это не так! Что делать, если у вас есть несколько файлов в репо? Клонирование будет занимать возрасты (в любое время более 1 минуты), а переход филиала - всего лишь один момент (<1 секунда). Все еще использование названных ветвей будет загрязнять журнал изменений. Разве это не тупик? Или я чего-то не хватает? – seler

+0

Okay seler; Звучит как модификация его первоначального аргумента; Клоны хороши там, где накладные расходы на несколько полных копий не важны для вас или когда вы можете использовать символические ссылки/hardlinks hg для уменьшения стоимости отдельных локальных рабочих копий на каждую ветку. –

5

Основное отличие, насколько я знаю, это то, что вы уже заявили: именованные разветвленные находятся в одном хранилище. Названные ветви имеют все удобное в одном месте. Отдельные репозитории меньше и легко перемещаются. Причина в том, что есть две мысли о том, что нет явного победителя. Какие бы стороны аргументов вам больше всего нравятся, вероятно, тот, с которым вам следует пойти, потому что, скорее всего, их окружающая среда наиболее похожа на вашу.

29

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

Одним из разочарований Mercurial является то, что, похоже, нет простого способа создать недолговечную ветку, поиграть с ней, отказаться от нее и собрать мусор. Филиалы навсегда. Я сочувствую никогда не отказываться от истории, но супер-дешевые одноразовые ветки - это функция git, которую я бы очень хотел увидеть в hg.

+20

Вы можете легко создать такую ​​ветку функций: «hg update» в точку вашего филиала, отредактировать и «hg commit». Вы создали новую линию развития - новые коммиты будут расширять эту ветвь. Используйте «hg clone -r», чтобы избавиться от него, или удалите его в строке «hg strip». Поэтому, пожалуйста, не разочаровывайтесь, или приходите в списки рассылки Mercurial с вашими запросами на функции. –

+8

Похоже, что 'hg strip' - это то, что я хочу. Почему не удается удалить ветви заявки на онлайн-документацию? –

+1

Norman: вам нужно включить расширение, например mq или histedit (~ 'git rebase -i'), чтобы получить деструктивное поведение с Mercurial. Затем вы можете удалить нежелательные ветви. –

2

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

14

Вы должны сделать как.

Начните с принятого ответа от @Norman: используйте один репозиторий с одной и той же ветвью на выпуск.

Затем у вас есть один клон для каждой ветви релиза для строительства и тестирования.

Одним из ключевых замечаний является то, что даже если вы используете несколько репозиториев, вам следует избегать использования transplant для перемещения наборов изменений между ними, потому что 1) он меняет хеш, и 2) он может вводить ошибки, которые очень трудно обнаружить, когда есть конфликтующие изменения между изменением набора, которое вы пересаживаете, и целевой ветвью. Вы хотите сделать обычное слияние вместо этого (и без premerge: всегда визуально проверить слияние), что приведет в том, что @mg сказал в конце своего ответа:

График Мощь выглядит по-другому, но у него есть та же структура и конечный результат одинаков.

Более пространно, если вы используете несколько хранилищ, то «ствол» хранилище (или по умолчанию, основное, развитие, безотносительно) содержит ВСЕХ в ревизии ВСЕХ хранилищ. Каждый репозиторий релизов/филиалов - это просто одна ветвь в соединительной линии, все они сливаются обратно в ту или другую сторону, пока вы не захотите оставить старый выпуск. Таким образом, единственная реальная разница между этим основным репо и единственным репо в названной схеме филиала - это просто имена ветвей или нет.

Это должно сделать очевидным, почему я сказал «начните с одного репо». Это единственное репо - это единственное место, где вам когда-либо понадобится искать любой набор изменений в любом выпуске. Вы можете дополнительно пометить набор изменений в ветвях выпуска для управления версиями. Он концептуально понятен и прост и упрощает администрирование системы, так как это единственное, что абсолютно необходимо для того, чтобы быть доступным и восстанавливаемым все время.

Но тогда вам все равно нужно поддерживать один клон на каждую ветвь/выпуск, которую нужно построить и протестировать. Это тривиально, как вы можете hg clone <main repo>#<branch> <branch repo>, а затем hg pull в ветке repo будет только тянуть новые изменения на этой ветке (плюс предки смены изменений на более ранних ветвях, которые были объединены).

Эта установка лучше всего подходит в ядре Linux фиксации модель одного съемника (это не чувствовать себя хорошо, чтобы действовать как лорд Линус. В нашей компании мы называем роль, интегратора), в качестве основного репо является единственным что разработчики должны клонировать, и съемник должен втягиваться. Техническое обслуживание отраслевых репозиториев исключительно для управления выпуском и может быть полностью автоматизировано. Разработчикам никогда не нужно тянуть с/push на репозитории филиалов.


Настоящий пример @ мг, переработанный для этой установки. Исходная точка:

[a] - [b] 

Сделайте именованную ветку для выпускной версии, скажем «1.0», когда вы попадете в альфа-версию. Фиксировать исправление ошибок на нем:

[a] - [b] ------------------ [m1] 
     \    /
      (1.0) - [x] - [y] 

(1.0) не является реальной, поскольку по имени ревизии филиал не существует, пока вы не зафиксируете. (Вы можете сделать тривиальный коммит, например, добавить тег, чтобы убедиться, что именованные ветви правильно созданы.)

Слияние [m1] является ключом к этой настройке. В отличие от репозитория разработчика, где может быть неограниченное количество головок, вы НЕ хотите иметь несколько глав в своем основном репо (за исключением старой ветви «мертвого выпуска», как упоминалось ранее). Поэтому всякий раз, когда у вас есть новые изменения в ветвях выпуска, вы должны немедленно слить их обратно в ветку по умолчанию (или в более позднюю ветку выпуска). Это гарантирует, что исправление ошибок в одном выпуске также включено во все последующие выпуски.

В развитии того времени по отрасли по умолчанию продолжает к следующей версии:

  ------- [c] - [d] 
     /
[a] - [b] ------------------ [m1] 
     \    /
      (1.0) - [x] - [y] 

И, как обычно, вам нужно объединить две головы по умолчанию филиала:

  ------- [c] - [d] ------- 
     /      \ 
[a] - [b] ------------------ [m1] - [m2] 
     \    /
      (1.0) - [x] - [y] 

И это 1.0 клон:

[a] - [b] - (1.0) - [x] - [y] 

Теперь это упражнение для добавления следующей ветви выпуска , Если он равен 2.0, он обязательно отключит значение по умолчанию. Если это 1.1, вы можете выбрать ветку 1.0 или по умолчанию. Независимо от того, любой новый набор изменений 1.0 должен быть сначала объединен с следующей ветвью, а затем по умолчанию. Это можно сделать автоматически, если нет конфликта, что приводит к простому слиянию.

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

  1. Единый авторитетный репозиторий, содержащий полный набор изменений и историю версий.
  2. Четкое и упрощенное управление выпуском.
  3. Прозрачный и упрощенный рабочий процесс для разработчиков и интеграторов.
  4. Облегчать итерации рабочего процесса (обзор кода) и автоматизацию (автоматическое пустое слияние).

сам UPDATE does this рт.ст.: main repo содержит по умолчанию и устойчивые ветви, а stable repo является стабильной ветви клон. Однако он не использует ветку с версией, поскольку теги версии вдоль стабильной ветви достаточно хороши для целей управления выпуском.

0

Я бы не советовал использовать названные ветви для версий. Для этого нужны теги. Именованные ветки предназначены для длительных переходов, таких как ветка stable.

Так почему бы не просто использовать теги? Простой пример:

  • Развитие происходит на одной ветви
  • Всякий раз, когда создается релиз, вы пометить его соответствующим образом
  • развития просто продолжает оттуда
  • Если у вас есть какие-то ошибки, чтобы исправить (или независимо) в определенном выпуске, вы просто обновляете свой тег, внесите свои изменения и совершите

Это создаст новую, неназванную голову на ветке default, ака. анонимная ветка, которая отлично подходит для hg. Затем вы можете в любой момент слить ошибку, которая возвращается обратно в основную дорожку разработки. Нет необходимости в названных ветвях.

+0

Это зависит от вашего процесса. Например, веб-приложение хорошо работает с иерархией ветвей stable/testing/devel. При создании настольного программного обеспечения у нас обычно есть ветвь развития (по умолчанию), а также один-три (!) Разных филиала в обслуживании. Трудно предсказать, когда нам, возможно, понадобится пересмотреть отрасль, и есть определенная элегантность в отношении того, что ветвь отслеживает версию major.minor. –

Смежные вопросы