Как Mercurial работает со многими разработчиками?

Я смотрю Mercurial-хранилища некоторых известных продуктов, например TortoiseHg и Python, и хотя я вижу, что несколько человек совершают изменения, временная шкала всегда выглядит довольно чистой, только одна ветвь движется вперед.

Однако скажите, что у вас 14 человек, работающих над одним и тем же продуктом, не скоро ли они попадут в ветхий кошмар с 14 параллельными ветвями в любой момент времени?

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

Когда они фиксируют, теперь у нас есть две ветки, а затем с 14 людьми, у нас быстрая ветка 10+ (возможно, не 14...), которые должны быть объединены обратно в значение по умолчанию.

Или... Что я не вижу здесь? Возможно, это не проблема?


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

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

Так что не это.

Мне интересно, как этот проект с открытым исходным кодом управляет такой чистой историей. Мне не важно (как один комментарий задавался вопросом), что история чиста, я имею в виду, что мы работаем параллельно, что репозиторий способен отражать это, тем лучше (на мой взгляд), однако эти хранилища я ' ve посмотрел, не имеет этого. Похоже, что они работают по модели Subversion, где вы не можете зафиксировать ее до того, как будете обновлены и объединены, и в этом случае история будет только одной прямой.

Итак, как они это делают?

Являются ли они "переустановкой" изменений, чтобы они, по-видимому, следовали за последним концом ветки, хотя первоначально они были немного исправлены в истории веток? Пересадить изменения, чтобы заставить их казаться "совершенными в основной ветке, чтобы начать?"

Или проекты, на которые я смотрел так медленно (на данный момент, я не смотрел далеко назад в истории), добавляя новые вещи, которые на самом деле они работали только один человек за раз?

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

Ответы

Ответ 1

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

Изменить. Поскольку Im ждет компиляции, здесь следует конкретный пример того, что я имею в виду:

> hg init
> echo test > a.txt
> hg addremove && hg commit -m "added a.txt"
> echo test > b.txt
> hg addremove && hg commit -m "added b.txt"
> hg update 0 # go back to initial revision
> echo test > c.txt
> hg addremove && hg commit -m "added c.txt"

Запуск hg glog теперь показывает эту (расходящуюся) историю с двумя ветвями:

@  changeset:   2:c79893255a0f
|  tag:         tip
|  parent:      0:7e1679006144
|  user:        mizipzor
|  date:        Mon Jul 05 12:20:37 2010 +0200
|  summary:     added c.txt
|
| o  changeset:   1:74f6483b38f4
|/   user:        mizipzor
|    date:        Mon Jul 05 12:20:07 2010 +0200
|    summary:     added b.txt
|
o  changeset:   0:7e1679006144
   user:        mizipzor
   date:        Mon Jul 05 12:19:41 2010 +0200
   summary:     added a.txt

Сделайте rebase, сделав changeet 1 в дочерний элемент 2, а не 0:

> hg rebase -s 1 -d 2

Теперь снова проверьте историю:

@  changeset:   2:ea0c9a705a70
|  tag:         tip
|  user:        mizipzor
|  date:        Mon Jul 05 12:20:07 2010 +0200
|  summary:     added b.txt
|
o  changeset:   1:c79893255a0f
|  user:        mizipzor
|  date:        Mon Jul 05 12:20:37 2010 +0200
|  summary:     added c.txt
|
o  changeset:   0:7e1679006144
   user:        mizipzor
   date:        Mon Jul 05 12:19:41 2010 +0200
   summary:     added a.txt

Presto! Одна линия.:)

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

Ответ 2

Или... Что я не вижу здесь? Возможно, это не проблема?

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

Это на практике означает, что 80%% слияний может быть сделано автоматически с помощью самого Mercurial.

Возьмем пример:

у вас есть:

[branch 1]  [branch2]
        \    /
         \  /
        [base]

Изменить: для ясности, с помощью ветки. Здесь я ссылаюсь на неназванные ветки.

Если у вас есть файл, измененный в branch 1, но тот же файл в branch 2 такой же, как в base, тогда выбирается версия в branch 1. Если файл изменен как в branch 1, так и в branch 2, файлы объединяются по строкам одним и тем же алгоритмом: если строка 1 в файле1 в branch 1 отличается от строки 1 в файле1 в base, но branch 2 и base имеют линию 1 равную, выбирается строка 1 в branch 1 (и так далее и т.д.).

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

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

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

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

Мы использовали синхронизацию реализованных функций каждый понедельник утром, и нам потребовалось около часа, чтобы объединить все, а затем сделать еженедельную сборку на сервере, чтобы дать QA (в плохие дни потребуется два члена команды два часа или так что тогда все будут тянуть изменения недели на своей машине и использовать их в качестве новой базы на неделю). Это было для команды из восьми разработчиков.

Ответ 3

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

В проекте Mercurial мы принимаем вклады в виде патчей, отправленных в список рассылки. Когда мы применяем теги с hg import, мы делаем неявный rebase на кончик ветки, над которой мы работаем. Это очень помогает в сохранении истории.

Что касается моих собственных изменений, я использую rebase или mq, чтобы линеаризовать вещи, прежде чем я их нажму, чтобы сохранить порядок в истории. Это в основном вопрос

hg push  # abort: creates new remote head
hg pull
hg rebase
hg push

Вы можете комбинировать pull и rebase, если хотите (hg pull --rebase), но мне всегда нравилось делать один шаг за раз.

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

Ответ 4

Ядро Linux хранится в тысячах хранилищ и, вероятно, в миллионах ветвей, и это, похоже, не создает проблемы. Для крупных проектов вам нужна стратегия репозитория (например, стратегия диктатора-лейтенанта), но наличие многих веток является основной силой современных DVCS, а не проблемой вообще.

Ответ 5

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

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

Ответ 6

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

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