Какие модели веток Git работают для вас?

379

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

  1. Рабочие процессы / модели ветвления

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

  2. Слияние с перебазированием (запутанный против последовательной истории)

    Стоит ли pull --rebaseждать или ждать слияния с основной линией, пока ваша задача не будет завершена? Лично я склоняюсь к слиянию, поскольку это сохраняет наглядную иллюстрацию того, на каком основании задача была начата и завершена, и я даже предпочитаю merge --no-ffдля этой цели. Однако у него есть и другие недостатки. Также многие не осознали полезного свойства слияния - то, что оно не коммутативно (слияние ветки темы в мастер не означает слияние мастера с веткой темы).

  3. Я ищу естественный рабочий процесс

    Иногда ошибки случаются, потому что наши процедуры не фиксируют конкретную ситуацию с простыми правилами. Например, исправление, необходимое для более ранних выпусков, должно, конечно, базироваться достаточно нисходящим, чтобы можно было объединить восходящий поток со всеми необходимыми ветвями (достаточно ли ясно использование этих терминов?). Однако бывает, что исправление попадает в мастер до того, как разработчик поймет, что его следует поместить дальше вниз по течению, и, если оно уже выдвинуто (еще хуже, объединено или что-то на его основе), то оставшаяся опция - выбор вишни, с связанные с этим опасности. Какие простые правила, как такие, вы используете?Также сюда входит неловкость одной тематической ветви, обязательно исключая другие тематические ветви (при условии, что они разветвлены от общей базовой линии). Разработчики не хотят завершать функцию, чтобы начать еще одно чувство, будто только что написанного кода больше нет

  4. Как избежать возникновения конфликтов слияния (из-за cherry-pick)?

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

  5. Как разложить на актуальные ветки?

    Мы понимаем, что было бы здорово собрать законченную интеграцию из веток тем, но часто работа наших разработчиков не была четко определена (иногда так просто, как "возиться"), и если какой-то код уже вошел в раздел "Разное", это не может быть удалено оттуда снова, согласно вопросу выше? Как вы работаете с определением / утверждением / окончанием / выпуском веток вашей темы?

  6. Правильные процедуры, такие как проверка кода и выпуск , конечно, были бы хороши.

    Но мы просто не можем держать вещи достаточно распутанными, чтобы справиться с этим - какие-либо предложения? интеграционные ветки, иллюстрации?

Ниже приведен список связанных вопросов:

Также посмотрите, что Plastic SCM пишет о разработке , ориентированной на задачи , и если Plastic не ваш выбор, изучите модель ветвления nvie и его вспомогательные сценарии .

HiQ CJ
источник
2
Ха, спасибо, это действительно так ... Я прочитал большую часть этого ... материала :-). Это то, что я знаю - не соглашаться на посредственное решение, но продолжать искать идеальное. Часто это ошибка, но в этом случае многое поставлено на карту, а имеющиеся решения слишком беспорядочные или плохие, и мне нужно продолжать искать. Поэтому я решил перечислить все проблемы, которые у меня есть с ним.
HiQ CJ
Блог Plastic SCM высказал свое мнение в обсуждении, по крайней мере, он проницателен: codicesoftware.blogspot.com/2010/08/…
HiQ CJ
1
Вы должны быть осторожны при использовании «merge --no-ff», проверьте это для некоторых предостережений sandofsky.com/blog/git-workflow.html
Doppelganger
1
@Doppelganger Мне было бы интересно узнать, как конкретно --no-ff предположительно способствует проблеме, описанной в ссылке, которую вы публикуете. Для меня описанная проблема - это сбой bisect с фиксацией контрольной точки и неспособность git обвинить в этом случае, но я не вижу, как «--no-ff» что-то меняет, в отличие от того, чтобы не использовать его. Автор жалуется, что слияние с --no-ff не приводит к изменению файла - но без него файл также не будет изменен, вы также увидите только старый коммит в своей истории, верно?
кодирование
Другая модель ветвления: модель кактуса barro.github.io/2016/02/… , основная линия модели bitsnbites.eu/a-stable-mainline-branching-model-for-git . Эта модель ветвления предлагает другой подход, чем gitflow.
Матье Момаль

Ответы:

91

Наиболее тревожная особенность, которую должны осознать новые разработчики DVCS, - это процесс публикации :

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

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

Сейчас же:

Рабочие процессы / модели ветвления :

каждый рабочий процесс предназначен для поддержки процесса управления выпусками , и он адаптирован для каждого проекта.
Что я могу добавить в рабочий процесс, о котором вы упомянули: каждый разработчик не должен создавать ветвь функций, а только ветку «текущего разработчика», потому что правда в том, что разработчик часто не знает, что именно его / ее ветка создаст: один особенность, несколько (потому что это оказалось слишком сложной функцией), ни одна (потому что не была готова вовремя к выпуску), другая особенность (потому что оригинальная «трансформировалась»), ...

Только «интегратор» должен создавать официальные ветви функций в «центральном» репо, которые затем могут быть выбраны разработчиками, чтобы перебазировать / объединить ту часть своей работы, которая соответствует этой функции.

Слияние с перебазированием (запутанный против последовательной истории) :

Мне нравится мой ответ, который вы упомянули (« Описание рабочего процесса для использования git для собственной разработки »)

Я ищу естественный рабочий процесс :

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

Как избежать возникновения конфликтов слияния (из-за cherry-pick)?

Как заявил Якуб Наребски в своем ответе , сбор вишни следует проводить в редких случаях, когда это необходимо.
Если ваша настройка включает в себя много вишни (то есть «это не редкость»), то что-то не так.

Будет ли применять тот же коммит в обратном порядке (как это сделать?)

git revert следует позаботиться об этом, но это не идеально.

Как разложить на актуальные ветки?

Пока ветвь еще не была распространена повсеместно, разработчик должен реорганизовать свою историю коммитов (когда он / она наконец увидит, что разработка принимает более определенную и стабильную форму) в:

  • несколько веток, если необходимо (одна с четко определенной функцией)
  • согласованный набор коммитов в пределах одной ветви (см. Trimming Git Checkins )

Правильные процедуры, такие как проверка кода и выпуск?

Интеграция веток (в выделенной интеграции) репо может помочь разработчику:

  • перебазировать его / ее разработку поверх ветки удаленной интеграции (pull --rebase)
  • решить локально
  • подтолкнуть развитие к этому репо
  • посоветуйтесь с интегратором, который не приведет к путанице;)
VonC
источник
@UncleCJ: как вы видите, это не совсем окончательный ответ на ваш «последний вопрос»;)
VonC
Я понимаю, и у меня есть хорошее чувство иронии, это нормально ;-)
HiQ CJ
3
@UncleCJ upstream - это то место, откуда вы регулярно извлекаете информацию из моего поста, где заканчиваются все коммиты (версия релиза или транк на языке SVN). Вниз по течению все ниже их. Отправка материала в восходящем направлении - это процесс объединения его с репозиторием релиза (например, в linux-2.6), а в нисходящем направлении - это изменения, происходящие оттуда, или из вашего репозитория, как, например, менеджер по разработке такой функции для ваших миньонов ... I Подлая команда.
2
@UncleCJ: «Мне все еще сложно урезать ваши проверки, чтобы получить строго последовательную историю»: это проще с Git1.7, rebase --interactive --autosquashкоторый автоматически перемещает все коммиты с тем же началом другого сообщения коммита. Если эти коммиты используют номер билета (например), даже если исправления, связанные с этим билетом, не были сделаны последовательно в то время, автоматическое сквош позволяет быстро изменить порядок этих коммитов.
VonC
1
@UncleCJ: «строго последовательная история (это необходимо или нет ?!)»: не всегда необходимо, но помогает отслеживать функциональные зависимости ( stackoverflow.com/questions/881092/… ) и семантические конфликты ( stackoverflow.com/questions / 2514502 /… )
VonC
21

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

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

Другие репозитории делают некоторые разработки. Идея состоит в том, чтобы клонировать из linux-2.6, разветвлять столько раз, сколько вам нужно, до того момента, пока у вас не появится рабочая «новая» функция. Затем, когда все будет готово, вы можете сделать его доступным для того, кто считается доверенным, кто перетянет эту ветку из вашего репозитория в свою и объединит ее с основным потоком. В ядре linux это происходит на нескольких уровнях (доверенные лейтенанты), пока не достигнет linux-2.6.git, после чего оно становится «ядром».

Теперь вот где это сбивает с толку. Имена ветвей вообще не должны быть одинаковыми в разных репозиториях. Так что я могу git pull origin master:vanilla-codeи получить ветку от originмастера в ветке в моем хранилище под названием vanilla-code. Если я знаю, что происходит, это на самом деле не имеет значения - оно распространяется в том смысле, что все репозитории являются одноранговыми, а не просто используются несколькими компьютерами, такими как SVN.

Итак, имея в виду все это:

  1. Я думаю, что это зависит от каждого программиста, как они делают свое ветвление. Все, что вам нужно, - это центральный репозиторий для управления выпусками и т. Д. Может быть и Trunk head. Релизы могут быть тегами или ветвями, а исправления, вероятно, сами по себе являются ветвями. На самом деле, я бы сделал выпуски ветвями, чтобы вы могли их исправлять.
  2. Я бы слился, а не перебазировал. Если, например, взять хранилище, клонировать его, ветвь и сделать некоторые Дев, а затем вытащить из вашей originследует, в вашем хранилище, вероятно , сделать еще одну ветку и объединить последнюю masterв yourbranchтак , что кто - то может тянуть изменения с минимальными усилиями возможный. По моему опыту, очень редко возникает необходимость по-настоящему перебазировать.
  3. Я думаю, что это случай понимания того, как работает Git и что он может делать. Это требует времени и много хорошего общения - я действительно начал понимать, что происходит, когда начал использовать git с другими разработчиками и даже сейчас, в некоторых вещах, в которых я не уверен.
  4. Конфликты слияния полезны. Я знаю, я знаю, вы хотите, чтобы все это работало, но факт - изменения кода, и вам нужно объединить результаты во что-то, что работает. Конфликты слияний на самом деле просто больше программирования. Я никогда не находил простого объяснения того, что с ними делать, поэтому вот оно: обратите внимание на файлы, которые имеют конфликты слияния, перейдите и измените их на то, что они должны быть, git add .а затем git commit.
  5. Однако это устраивает. Как я уже сказал, каждый пользовательский репозиторий git является своим собственным, и имена веток не обязательно должны быть одинаковыми . Например, если у вас есть промежуточный репозиторий, вы можете применить схему именования, но вам не нужно это делать для каждого разработчика, только в репозитории релизов.
  6. Это этап слияния. Вы объединяетесь только с ветками релизов и т. Д., Если считаете, что код проверяется / проходит качественное тестирование.

Надеюсь, это поможет. Я понимаю, что VonC только что опубликовал очень похожее объяснение ... Я не могу набрать достаточно быстро!

Отредактируйте некоторые дальнейшие мысли о том, как использовать git в коммерческих условиях, так как это кажется актуальным для OP из комментариев:

  • Репозиторий релизов, как мы его назовем product.git, доступен нескольким старшим программистам / техническим специалистам, ответственным за то, чтобы реально заботиться о самом продукте. Они аналогичны роли сопровождающих в OSS.
  • Эти программисты, вероятно, также частично руководят разработкой новых версий, поэтому они могут также кодировать себя и поддерживать репозитории varios. Они могут управлять промежуточными репозиториями для действительно новых функций, а также могут иметь свои собственные репозитории.
  • Под ними находятся программисты, отвечающие за разработку отдельных битов. Например, кто-то может нести ответственность за работу интерфейса. Поэтому они управляют хранилищем UI.git.
  • Ниже приведены настоящие программисты, которые разрабатывают функции как свою повседневную работу.

Так что же происходит? Ну, все в начале каждого дня извлекают данные из «восходящего» источника, то есть из репозитория релизов (который также, вероятно, будет содержать последние материалы из предыдущих дней разработки). Каждый делает это напрямую. Это пойдет на ветку в их хранилище, возможно, под названием «master» или, может быть, если вы меня называете «последним». Затем программист выполнит некоторую работу. Эта работа может быть чем-то, в чем они не уверены, поэтому они делают ветку, делают работу. Если это не работает, они могут удалить ветку и вернуться назад. Если это произойдет, им придется объединиться с основной ветвью, над которой они сейчас работают. Мы скажем, что это программист пользовательского интерфейса, над которым latest-uiон работает, git checkout latest-uiа затемgit merge abc-ui-mywhizzynewfeature, Затем он говорит своему техническому руководителю (руководству по пользовательскому интерфейсу): «Я выполнил такую ​​задачу, вытащил меня». Так что ведет интерфейс git pull user-repo lastest-ui:lastest-ui-suchafeature-abc. Затем ведущий пользовательского интерфейса смотрит на него в этой ветке и говорит, что на самом деле это очень хорошо, я объединю его ui-latest. Затем он может сказать всем, кто ниже его, чтобы он брал у него ui-latestветки или любое другое имя, которое они им дали, и разработчики изучают эту особенность. Если команда довольна, лидер UI может попросить, чтобы лидер тестирования вытащил из него и объединил изменения. Это распространяется на всех (ниже по течению от изменений), которые тестируют его и представляют отчеты об ошибках и т. Д. Наконец, если функция проходит тестирование и т. Д., Один из главных технических руководителей может объединить ее с текущей рабочей копией программы, после чего все изменения затем распространяются обратно вниз. И так далее.

Это не «традиционный» способ работы, он предназначен для «равноправного управления», а не «иерархического» типа SVN / CVS. По сути, каждый имеет доступ к коммитам, но только локально. Это доступ к репозиторию, и какой репозиторий вы определяете как репозиторий релиза, который позволяет вам использовать иерархию.


источник
Большое спасибо за ваш обширный ответ (и голоса), я прочитаю его еще пару раз, чтобы извлечь из него полезную информацию. Тем не менее, мы - компания, а не комитет по разработке OSS ;-), и я должен помочь своим разработчикам с более четкими рекомендациями, чем «возиться, как вы хотите, в своем собственном репозитории». Давайте посмотрим, куда ведет этот пост, я чувствую хороший импульс, продолжайте в том же духе!
HiQ CJ
@VonC Спасибо. @UncleCJ верно, но у вас, я уверен, есть менеджеры релизов и т. Д. Любой, кто имеет доступ к хранилищу, может сделать это. Что касается разработки, почему бы не дать разработчикам свободу, в пределах разумного, отделяться? Если у вас есть протокол для согласования слияний и ваш центральный репозиторий назван так, как вам нравится, проблем нет. Сказав это, общая схема именования не плохая идея. Я склонен использовать инициалы-версии-функции-подветки для личных веток и версию для веток.
@UncleCJ Я добавил пример того, как это может работать в компании. По сути, это роли OSS, замененные менеджерами, но вы поняли идею. Он имеет дополнительное преимущество перед SVN в том, что ваши разработчики могут работать и в автономном режиме (им нужна только сеть, чтобы тянуть / толкать), и я думаю, что это облегчает тестирование функций, если вы хорошо это реализуете.
Вау, это на самом деле отличный пример, мы можем начать использовать что-то подобное для выпуска. Я не имел в виду так много, что, поскольку мы не делаем OSS, все должны регулироваться, мы на самом деле довольно маленькая и сплоченная команда, но мы должны постараться эффективно сотрудничать в сжатые сроки, а также учиться в команде. , Вот почему я здесь задаю эти глупые вопросы, чтобы потом помочь остальной команде :-). Я также понял из #git, что плохо определенная базовая линия в сочетании с давлением, чтобы сократить время выполнения заказа, заставляет нас встать на ноги ... вернемся позже.
HiQ CJ
Это достаточно справедливо - я был там недавно, именно так я и взял этот пример, попробовав его и потерпев неудачу ... и также адаптируясь к методам работы некоторых проектов OSS. Я думаю, что настоящая важная персона в том, что не имеет значения, как вы разветвляетесь и где находятся ваши репозитории ... вы можете определить их так, как хотите, что в любом случае было для меня шоком! Но это позволяет делать некоторые интересные вещи. В любом случае, удачи и веселья!
9

Модель, которую я использовал с хорошими результатами, выглядит следующим образом:

«Благословенный» репо, который все толкают и тянут в / из, в основном топология клиент-сервер.

Там нет главной ветки, поэтому ни один разработчик не может вставить любой код в «mainline».

Все разработки происходят по тематическим веткам. Мы называем имена в пространстве имен, чтобы легко определить, кто за это отвечает: jn / newFeature или jn / issue-1234

Существует также соотношение между ветвями и канбан / скрам-картами на доске.

Чтобы освободить ветку, ее подталкивают к благословенному репо, и канбан-карта перемещается в готовое для просмотра.

Затем, если ветка принята рецензией, она является кандидатом на выпуск.

Выпуск происходит, когда набор принятых ветвей объединяется и помечается номером версии.

При добавлении нового тега в благословенное хранилище появляется новая возможная база для новых функций.

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

Джон Нильссон
источник
2

Лично я стараюсь хранить только готовый к выпуску код в основной ветке.

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

Я также пытаюсь использовать общие правила именования веток, такие как:

  • багфикс / recursive_loop
  • багфикс / sql_timeout
  • Функция / new_layout
  • Функция / enhanced_search
ксеро
источник