Мой офис хочет, чтобы бесконечная ветвь сливалась как политика; какие у нас есть другие варианты?

Мой офис пытается выяснить, как мы обрабатываем разветвления ветвей и слияния, и мы столкнулись с большой проблемой.

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

Теперь, ИМХО, естественный способ справиться с этим - вырезать боковую ветвь в единую фиксацию. master продолжает двигаться вперед; как и следовало ожидать - мы не ретроактивно отбрасываем месяцы параллельного развития в историю master. И если кто-то нуждается в лучшем разрешении для истории sidebranch, ну, конечно, он все еще там - это просто не в master, это в sidebranch.

Вот проблема: я работаю исключительно с командной строкой, но в остальной части моей команды используется GUIS. И я обнаружил, что GUIS не имеет разумного варианта для отображения истории из других ветвей. Поэтому, если вы достигнете фиксации сквоша, сказав, что «это развитие сжато из ветки XYZ», это боль в огромная , чтобы посмотреть, что находится в XYZ.

В SourceTree, насколько я могу найти, это огромная головная боль: если вы находитесь на master, и хотите просмотреть историю из master+devFeature, вам либо нужно проверить master+devFeature out (касание каждого отдельного файла), либо прокрутить журнал, отображая ВСЕ ветки вашего репозитория параллельно до тех пор, пока вы найдете нужное место. И удачи, выясняя, где вы там.

Мои товарищи по команде, совершенно справедливо, не хотят, чтобы история развития настолько недоступна. Таким образом, они хотят, чтобы эти большие, длинные ветви разработки были объединены, всегда с фиксацией слияния. Они не хотят, чтобы какая-либо история не была сразу доступна из ведущей ветки.

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

Есть ли у нас какой-либо вариант, кроме того, что мы постоянно объединяем sidebranches в master слиянием? Или, есть ли причина, по которой постоянно используется слияние-коммиты, не так плохо, как я боюсь?

117 голосов | спросил Standback 19 MonEurope/Moscow2016-12-19T18:23:22+03:00Europe/Moscow12bEurope/MoscowMon, 19 Dec 2016 18:23:22 +0300 2016, 18:23:22

7 ответов


240

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

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

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

  • Вы выкалываете некоторые коммиты и отмечаете в сообщении о фиксации, что история сжатых данных доступна в исходном commit abcd123.
  • Вы удаляете [1] все ветви или теги, которые включают abcd123, поскольку они объединены.
  • Вы разрешаете сборщику мусора.

[1]: Некоторые серверы Git позволяют защищать ветви от случайного удаления, но я сомневаюсь, что вы хотите сохранить все ветви вашей функции на вечность.

Теперь вы больше не можете искать это сообщение - его просто не существует.

Ссылка на имя филиала в сообщении фиксации еще хуже, так как имена ветвей являются локальными для репо. Что такое master+devFeature в вашей локальной проверке, может быть doodlediduh в моем. Филиалы просто перемещают метки, указывающие на некоторый объект фиксации.

Из всех методов перезаписи истории rebasing является наиболее мягким, поскольку он дублирует полные коммиты со всей их историей и просто заменяет родительский фиксатор.

Чтобы история master включала в себя всю историю всех ветвей, которые были объединены в нее, это хорошо, потому что это представляет реальность. [2] Если бы существовала параллель разработки, которые должны быть видны в журнале.

[2]: По этой причине я также предпочитаю, чтобы явные комманды слияния выполнялись над линеаризованной, но в конечном итоге поддельной историей, вызванной перезагрузкой.

В командной строке git log пытается упростить упрощение отображаемой истории и сохранить все отображаемые фиксации релевантными. Вы можете настроить упрощение истории в соответствии с вашими потребностями. Возможно, у вас возникнет соблазн написать собственный инструмент журнала git, который будет обрабатывать граф фиксации, но, как правило, невозможно ответить «было ли это обязательство первоначально зафиксировано в той или иной ветви?». Первым родителем слияния является предыдущий HEAD, то есть фиксация в ветви, в которую вы входите. Но это предполагает, что вы не делали обратного слияния с мастером в ветви функции, а затем переадресовали мастер на слияние.

Лучшим решением для долгосрочных ветвей, с которыми я столкнулся, является предотвращение ветвей, которые сливаются только через пару месяцев. Слияние является самым простым, когда изменения являются последними и малыми. В идеале вы будете сливаться не реже одного раза в неделю. Непрерывная интеграция (как и в экстремальном программировании, а не в «настройке сервера Jenkins») даже предполагает множественные слияния в день, т. Е. Не поддерживать отдельные ветви функций, но совместно использовать ветку развития в качестве команды. Слияние перед функцией QA'd требует, чтобы функция скрывалась за флагом функции.

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

История переписывания может иметь смысл для действительно огромных проектов, когда есть несколько миллионов строк кода и сотни или тысячи активных разработчиков. Не вызывает сомнений, почему такой большойпроект должен быть единственным реестром git вместо того, чтобы быть разделенным на отдельные библиотеки, но в этом масштабе более удобно, если центральное репо содержит только «списки» отдельных компонентов. Например. ядро Linux использует раздачу, чтобы сохранить основную историю управляемой. Некоторые проекты с открытым исходным кодом требуют, чтобы исправления отправлялись по электронной почте вместо слияния уровня git.

ответил amon 19 MonEurope/Moscow2016-12-19T19:31:56+03:00Europe/Moscow12bEurope/MoscowMon, 19 Dec 2016 19:31:56 +0300 2016, 19:31:56
108

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

Вот пример из одного из наших репозиториев. Мы используем модель pull-request, поэтому каждая функция выглядит как ваши длинные ветви в истории, хотя обычно они работают только неделю или меньше. Отдельные разработчики иногда предпочитают сквоивать свою историю до слияния, но мы часто соединяемся с функциями, так что это относительно необычно. Вот несколько лучших коммитов в gitk, gui, который поставляется в комплекте с git:

 стандартное представление gitk

Да, немного путаницы, но нам также нравится, потому что мы можем точно видеть, кто что изменил в какое время. Он точно отражает нашу историю развития. Если мы хотим увидеть представление более высокого уровня, одно затягивание запроса объединяется за раз, мы можем посмотреть следующее представление, которое эквивалентно команде git log --first-parent:

 просмотр gitk с -first-parent

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

ответил Karl Bielefeldt 19 MonEurope/Moscow2016-12-19T20:34:40+03:00Europe/Moscow12bEurope/MoscowMon, 19 Dec 2016 20:34:40 +0300 2016, 20:34:40
32
  

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

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

Если вам нужно это сделать, тогда можно слить git с параметром --no-ff, чтобы истории сохранялись в отдельной ветви. Коммиты все равно будут отображаться в объединенной истории, но также могут быть видны отдельно в ветви признаков, так что, по крайней мере, можно определить, в какую линию развития они были частью.

Я должен признать, что когда я впервые начал использовать git, мне показалось немного странным, что ветвь завершается в той же истории, что и главная ветвь после слияния. Это было немного смущающе, потому что казалось, что эти коммиты не принадлежали этой истории. Но на практике это не совсем то, что действительно больно, если учесть, что интеграционная ветка просто такова - целая цель заключается в объединении ветвей функций. В нашей команде мы не сквошем, и мы часто совершаем слияние. Мы все время используем -no-ff, чтобы убедиться, что его легко увидеть точную историю какой-либо функции, если мы хотим ее исследовать.

ответил Brad Thomas 19 MonEurope/Moscow2016-12-19T22:11:22+03:00Europe/Moscow12bEurope/MoscowMon, 19 Dec 2016 22:11:22 +0300 2016, 22:11:22
10

Сокрушая длинную боковую ветку, вы потеряете много информации.

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

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

ответил Pierre.Sassoulas 20 TueEurope/Moscow2016-12-20T13:55:49+03:00Europe/Moscow12bEurope/MoscowTue, 20 Dec 2016 13:55:49 +0300 2016, 13:55:49
9

Позвольте мне прямо и ясно ответить на ваши вопросы:

  

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

Обычно вы не хотите, чтобы ваши филиалы были несинхронизированы в течение нескольких месяцев.

В вашей ветке функций есть что-то в зависимости от вашего рабочего процесса; давайте просто назовем его master для простоты. Теперь, всякий раз, когда вы фиксируете мастер, вы можете и должны git checkout long_running_feature ; git rebase master. Это означает, что ваши ветви по дизайну всегда синхронизированы.

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

  

Теперь, ИМХО, естественный способ справиться с этим - вырезать боковую ветвь в единую фиксацию.

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

Обязательно укажите опцию --no-ff, конечно; слияние без --no-ff должно в вашем сценарии строго запрещаться. К сожалению, --no-ff не является значением по умолчанию; но я считаю, что есть возможность, которую вы можете установить, что делает это так. См. git help merge для чего --no-ff (вкратце: он активирует поведение, описанное в предыдущем абзаце), это важно.

  

мы не ретроактивно сбрасываем месяцы параллельного развития в историю мастера.

Абсолютно нет - вы никогда не сбрасываете что-то «в историю» какой-либо отрасли, особенно не с фиксацией слияния.

  

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

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

Посмотрите, что я сделал? Все, что вы описываете для вашего сквош-фиксации, - прямо там с фиксацией слияния --no-ff.

  

Вот проблема: я работаю исключительно с командной строкой, но в остальной части моей команды используется GUIS.

(Боковое замечание: я почти исключительно работаю с командной строкой (ну, это ложь, я обычно использую emacs magit, но это еще одна история - если я не в удобном месте с моей индивидуальной настройкой emacs, я предпочитайте также командную строку). Но, пожалуйста, сделайте себе одолжение и попробуйте как минимум git gui один раз. так гораздо эффективнее выбирать строки, куски и т. д. для добавление /отмена добавляет.)

  

И я обнаружил, что GUIS не имеет разумного варианта отображения истории из других ветвей.

Это потому, что то, что вы пытаетесь сделать, полностью противоречит духу git. git строит из ядра на «направленном ациклическом графе», что означает, что большая часть информации находится в отношениях между родителями и дочерними элементами. И, для слияний, это означает, что истинное слияние совершается с двумя родителями и одним ребенком. Графические интерфейсы ваших коллег будут прекрасны, как только вы скомпилируете слияние no-ff.

  

Итак, если вы достигнете фиксации сквоша, сказав: «Это развитие, раздавленное изветви XYZ ", это огромная боль, чтобы посмотреть, что находится в XYZ.

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

  

Таким образом, они хотят, чтобы эти большие, длинные расширения-sidebranches объединились, всегда с фиксацией слияния.

И они абсолютно правы. Но они не «объединены в », они просто слиты. Слияние - это действительно сбалансированная вещь, у нее нет предпочтительной стороны, которая объединяется «в» другую (git checkout A ; git merge B точно такая же, как git checkout B ; git merge A, за исключением незначительных визуальных различий, таких как ветви, которые меняются местами в git log и т. Д.).

  

Они не хотят, чтобы какая-либо история не была сразу доступна из основной ветви.

Это совершенно правильно. В то время, когда нет несвязанных функций, у вас будет одна ветвь master с богатой историей, инкапсулирующей все строки фиксации функций, которые когда-либо были, возвращаясь к git init зафиксировать с начала времени (обратите внимание, что я специально избегал использовать термин «ветви» во второй части этого абзаца, потому что история в то время больше не является «ветвями», хотя граф фиксации будет довольно разветвленным).

  

Я ненавижу эту идею;

Затем вы испытываете небольшую боль, так как вы работаете с инструментом, который используете. Подход git очень элегантный и мощный, особенно в области ветвления /слияния; если вы сделаете это правильно (как указано выше, особенно с помощью --no-ff), он чередований и ограничений перенаправляется на другие подходы (например, беспорядок подрывной деятельности с параллельными структурами каталогов для ветвей) .

  

это означает бесконечную, невозмутимую путаницу параллельной истории развития.

Бесконечный, параллельный - да.

Невозможно, путать - нет.

  

Но я не вижу, какая у нас альтернатива.

Почему бы не работать так же, как изобретатель git, ваши коллеги и остальной мир делать каждый день?

  

Есть ли у нас какой-либо вариант, кроме того, что мы постоянно объединяем sidebranches в master с слиянием? Или, есть ли причина, что постоянное использование слияний-коммитов не так плохо, как я боюсь?

Нет других вариантов; не так плохо.

ответил AnoE 21 WedEurope/Moscow2016-12-21T01:09:59+03:00Europe/Moscow12bEurope/MoscowWed, 21 Dec 2016 01:09:59 +0300 2016, 01:09:59
0

Лично я предпочитаю делать свою разработку в fork, а затем тянуть запросы для слияния в основной репозиторий.

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

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

Чтобы явным образом ответить на ваш вопрос:

  

Есть ли у нас какой-либо вариант, помимо постоянного слияния боковых ветвей с мастером слиянием?

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

ответил Wayne Werner 20 TueEurope/Moscow2016-12-20T00:23:11+03:00Europe/Moscow12bEurope/MoscowTue, 20 Dec 2016 00:23:11 +0300 2016, 00:23:11
-1

Элемент управления ревизией - мусор в мусоре.

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

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

С Git это можно сделать, сначала ветвями ветви признака (чтобы сохранить всю историю), затем (в интерактивном режиме), переустановив ветвь ветки признаков из мастера и затем сменив ветвь с разделением.

ответил DepressedDaniel 19 MonEurope/Moscow2016-12-19T22:41:45+03:00Europe/Moscow12bEurope/MoscowMon, 19 Dec 2016 22:41:45 +0300 2016, 22:41:45

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132