Гибкое и статическое ветвление (Git против Clearcase/Accurev)

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

Но в других системах, таких как Clearcase или Accurev, вы можете указать, как ветви заполняются с помощью какого-то механизма наследования: я имею в виду, что в Clearcase, используя config_spec, вы можете сказать: "получить все файлы, модифицированные на branch /main/issue001, и затем продолжайте с теми на / main или с этой конкретной базовой линией ".

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

Разве вы не пропустите это при использовании Git? Можете ли вы перечислить сценарии, где это наследование является обязательным?

Спасибо

Обновление Пожалуйста, прочитайте ответ VonC ниже, чтобы сфокусировать мой вопрос. Как только мы согласимся с тем, что "линейное хранилище" и SCM на основе DAG обладают различными возможностями, у меня возникает вопрос: каковы сценарии реальной жизни (особенно для компаний, в которых больше, чем OSS), где linear может сделать невозможное для DAG? Они стоят?

9 ответов

Решение

Чтобы понять, почему Git не предлагает нечто вроде того, что вы называете "механизмом наследования" (не включающим фиксацию), вы должны сначала понять одну из основных концепций этих SCM (например, Git против ClearCase).

  • ClearCase использует хранилище линейной версии: каждая версия элемента (файла или каталога) связана в прямой линейной зависимости с предыдущей версией того же элемента.

  • Git использует DAG - направленный ациклический граф: каждая "версия" файла фактически является частью глобального набора изменений в дереве, которое само является частью коммита. Предыдущая версия этого должна быть найдена в предыдущем коммите, доступном через единственный путь ациклического графа.

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

Ветвь - это ветвь в линейной истории заданной версии для данного правила выбора (все остальные правила выбора до этого все еще применяются, следовательно, эффект "наследования")

В DAG коммит представляет все "наследование", которое вы когда-либо получите; нет "накопительного" выбора версий. На этом графике есть только один путь, чтобы выбрать все файлы, которые вы увидите в данный момент (фиксация).
Ветвь - это просто новый путь в этом графе.

Чтобы применить в Git некоторые другие версии, вы должны либо:

  • объединить в вашу ветку какой-нибудь другой коммит (как в git pull, упомянутый в ответе stsquad) или
  • перебазировать вашу ветку (как упоминает Грег)

Но так как Git - это SCM на основе DAG, это всегда приведет к новому коммиту.

Что вы "теряете" с помощью Git, это какая-то "композиция" (когда вы выбираете разные версии с разными последовательными правилами выбора), но это не будет практично вD VCS (как в "Распределенном"): когда вы Создавая ветку с помощью Git, вы должны сделать это с начальной точкой и содержимым, четко определенным и легко реплицируемым в другие репозитории.

В чисто централизованной VCS вы можете определять свое рабочее пространство (в ClearCase, свое "представление", снимок или динамический) с любыми правилами, которые вы хотите.


jbhope добавляет в комментарии (и в своем вопросе выше):

Итак, как только мы увидим, что две модели могут достигать разных целей (линейный или DAG), у меня возникает вопрос: каковы сценарии реальной жизни (особенно для компаний, в которых более OSS), где линейный может сделать вещи, которые невозможно сделать для DAG? Они того стоят?

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

Рассмотрим эту "спецификацию конфигурации" (т.е. "спецификацию конфигурации" для правил выбора с ClearCase):

element /aPath/... aLabel3 -mkbranch myNewBranch
element /aPath/... aLabel2 -mkbranch myNewBranch

Он выбирает все файлы с пометкой "aLabel2"(и ответвление оттуда), за исключением тех, которые помечены"aLabel3"- и ответвление оттуда - (потому что это правило предшествует тому, которое упоминает"aLabel2").

Стоит ли оно того?

Нет.

На самом деле, UCM-версия ClearCase (методология " Unified Configuration Management", включенная в продукт ClearCase и представляющая все "лучшие практики", выведенные из базового использования ClearCase) не позволяет этого по причинампростоты. Набор файлов называется "компонентом", и если вы хотите выполнить ветвление для данной метки (известной как "базовая линия"), это будет переведено, как эта следующая спецификация конфигурации:

element /aPath/... .../myNewBranch
element /aPath/... aLabel3 -mkbranch myNewBranch
element /aPath/... /main/0 -mkbranch myNewBranch

Вы должны выбратьодну отправную точку (здесь, ' aLabel3и отправляйтесь оттуда. Если вы хотите также файлы из 'aLabel2 ', вы сделаете слияние со всеми'aLabel2'файлы к тем в'myNewBranch'.

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

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

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

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

Это легко сделать в системе DAG; это может быть сложнее в линейной системе (особенно с "Base ClearCase", где "спецификация конфигурации" может быть хитрой), но это обеспечивается с помощью методологии UCM того же линейного инструмента.

Вместо достижения этой "композиции" с помощью "уловки частного правила выбора" (с ClearCase, некоторым порядком выбора правил), вы достигаете этого только с помощью операций VCS (перебазирование или слияние), которые оставляют четкий след для всех (в противоположность этому). спецификацией конфигурации, частной для разработчика или распространенной среди некоторых, но не всех разработчиков). Опять же, он навязывает чувство согласованности, в отличие от "динамической гибкости", которую потом может быть трудно воспроизвести позже.

Это позволяет вам покинуть сферу VCS (Система контроля версий) и войти в сферу SCM (Управление конфигурацией программного обеспечения), которая в основном связана с "воспроизводимостью". И это (функции SCM) может быть достигнуто с помощью VCS на линейной основе или на базе DAG.

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

Я не совсем понимаю, о чем вы просите, но, похоже, семантика отслеживания git - это то, что вы хотите. Когда вы переходите из am origin, вы можете сделать что-то вроде:

git -t -b my_branch origin/master

И тогда будущие "git pull" автоматически объединят origin / master в вашу рабочую ветку. Затем вы можете использовать "git cherry -v origin/master", чтобы увидеть разницу. Вы можете использовать "git rebase" перед тем, как опубликовать свои изменения, чтобы очистить историю, но вы не должны использовать rebase, когда ваша история общедоступна (т.е. другие люди следуют этой ветке).

Я постараюсь ответить на ваш вопрос. (Я должен сказать здесь, что я не использовал GIT, только прочитайте об этом, поэтому, если что-то, что я упоминаю ниже, неверно, пожалуйста, исправьте меня)

"Можете ли вы перечислить сценарии, где это наследование является обязательным?"

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

Единственный сценарий, который я вижу, удобно иметь такое поведение "наследования" и использовать всю мощь спецификации конфигурации, когда вы хотите, чтобы ваш набор изменений был "изолированным", сопоставленным с задачей (devtask, CR, SR или что-то еще, что определяет цель / область вашего набора изменений)

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

Будучи пуристом, вынужденным совершать / объединять / перебазировать просто для того, чтобы иметь "определенную отправную точку", я думаю, это "загрязнит" вашу ветку, и вы в конечном итоге получите ваши изменения + другие изменения в вашей ветви / наборе изменений.

Когда / Где эта изоляция полезна? Приведенные ниже пункты могут иметь смысл только в контексте компаний, преследующих CMM и некоторые сертификаты ISO, и могут не представлять интереса для других типов компаний или OSS.

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

  • Проанализировать код на разных этапах проще, если в одной ветке находится только ваш код (без других изменений).

В больших проектах с несколькими командами и +500 разработчиками, активно работающими одновременно над одним и тем же базовым кодом (где деревья версий с отдельными графическими элементами выглядят как запутанная запутанная сеть с несколькими линиями загрузки, по одной для каждого крупного клиента или по одной для каждой технологии), большая конфигурация Спецификации, использующие композицию глубиной в несколько градусов, позволили этому количеству людей без проблем работать над тем, чтобы адаптировать один и тот же продукт / систему (базовый код) для различных целей. Используя эту конфигурационную спецификацию, динамически предоставлял каждой команде или подгруппе различное представление о том, что им нужно, и откуда они должны ветвиться (каскадно в нескольких случаях) без необходимости создавать промежуточные ветви интеграции или постоянно объединять и перебазировать все биты, с которых вам нужно начать. Код из одной и той же задачи / цели был разветвленным, но имел смысл. (Вы можете утверждать здесь "известную базовую линию" как принцип SCM, но простые метки, предусмотренные в письменном плане SCM, сделали свою работу.) Должно быть возможно решить эту проблему с помощью GIT (я полагаю, не динамическим способом), но я нахожу действительно трудно представить без этого поведения "наследования". Я предполагаю, что пункт, упомянутый VonC, "если разветвленные, все его файлы будут разветвляться с одной и той же уникальной отправной точки", был здесь нарушен, но помимо этого он был хорошо задокументирован на SCMP, я помню, что имелись веские деловые причины сделать это таким образом.

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

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

Таким образом, здесь можно сделать один вывод, только если ваш проект достаточно большой / сложный (и вы можете позволить себе SC Manager в течение всего срока его существования:)), тогда вы только начнете думать, если вам нужно поведение "наследования" или действительно универсальный инструмент, в противном случае вы перейдете непосредственно к бесплатному инструменту, который уже позаботится о согласованности вашего SCM ... но могут быть другие факторы в инструменте SCM, которые могут заставить вас придерживаться одного или другого....читать дальше..

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

Я должен добавить, что мы используем "добрый ол", а не UCM. Полностью согласен с VonC в том, что хорошая методология позволяет "направлять" гибкость в сторону более согласованной конфигурации. Хорошая вещь заключается в том, что CC довольно гибкий, и вы можете найти (не без особых усилий) хороший способ создать единообразные вещи, в то время как в других SCM вы можете иметь его бесплатно. Но, например, здесь (и в других местах, где я работал с CC) для проектов на C/C++ мы не можем позволить себе цену отсутствия функции winkin (повторного использования объектов Derive), которая сокращает время компиляции в несколько раз. Можно утверждать, что лучший дизайн, более отсоединенный код и оптимизация Makefiles могут уменьшить необходимость компиляции всего, но есть случаи, когда вам нужно компилировать всего зверя много раз в день, и совместное использование DO сохраняет куча времени / денег. Там, где я сейчас нахожусь, мы стараемся использовать как можно больше бесплатных инструментов, и я думаю, что мы избавимся от CC, если сможем найти более дешевый или бесплатный инструмент, который реализует функцию winkin.

Я закончу с чем-то, что упомянул Пол, разные инструменты лучше других для разных целей, но я добавлю, что вы можете избавиться от некоторых ограничений инструмента, имея согласованный процесс и без ущерба для воспроизводимости, ключевые моменты от SCM. конец, я думаю, ответ на него стоит? зависит от вашей "проблемы", SDLC, который вы используете, ваших процессов SCM и наличия каких-либо дополнительных функций (например, winkin), которые могут быть полезны в вашей среде.

мои 2 цента

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

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

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

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

Изначально мы использовали модель наследования во всех выпусках, где более поздние были потомками более ранних. Некоторое время это работало хорошо, но со временем стало неуправляемым. Серьезные архитектурные различия между выпусками сделали неизбежное наследование изменений плохой идеей. Да, вы можете поместить снимок между ними, чтобы заблокировать наследование, но тогда все изменения должны быть перенесены вручную, и единственное реальное различие между parent-snapshot-child и параллельными не наследующими потоками состоит в том, что весь графический вид потока постоянно сдвигается вниз и справа, который является PITA.

Одна очень хорошая вещь в AccuRev - это то, что у вас всегда есть этот выбор. Это не внутреннее ограничение архитектуры вашей программы SCM.

Вы заметили, что вы также можете проверять определенные версии файлов с помощью GIT?

Просто используйте это:

git checkout [< tree-ish >] [--] < paths >

Как и в случае с конфигурацией, любая рабочая версия файла (пути) может быть загружена в рабочее дерево. Цитата из документации git-checkout:

Следующая последовательность проверяет основную ветвь, возвращает Makefile на две ревизии назад, удаляет hello.c по ошибке и возвращает его из индекса:

$ git checkout master             
$ git checkout master~2 Makefile             
$ rm -f hello.c            
$ git checkout hello.c            

Что касается схемы наследования, используемой accurev: пользователи GIT, вероятно, "поймут" все это, когда взглянут на git-flow (см. Также: http://github.com/nvie/gitflow и http://jeffkreeftmeijer.com/ 2010 / Почему вы не используете Git-потока /)

Эта модель ветвления GIT более или менее делает (вручную / с помощью инструмента git-flow) то, что accurev делает "из коробки" автоматически и с отличной поддержкой графического интерфейса.

Похоже, GIT может делать то, что делает accurev. Поскольку я никогда не использовал git / git-flow изо дня в день, я не могу сказать, как это работает, но выглядит многообещающе. (Минус правильная поддержка графического интерфейса:-)

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

Если это те различия, о которых мы говорим, то я думаю, что "линейный" и "DAG" - сбивающий с толку способ отличить эти системы SCM. В ClearCase все версии файла называются "деревом" версии файла, но на самом деле это ориентированный ациклический граф! Реальное отличие от Git заключается в том, что группы DAG ClearCase существуют для каждого файла. Поэтому я думаю, что вводить в заблуждение ClearCase не-DAG, а Git - DAG.

(КСТАТИ ClearCase версии своих каталогов аналогично своим файлам - но это другая история.)

Я не уверен, что вы что-то спрашиваете, но вы демонстрируете, что потоки Accurev - это инструменты, отличные от веток Git (или SVN). (Я не знаю, Clearcase.)

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

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

Разные инструменты хороши для разных целей; полезно спросить, для чего каждый хорош.

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