Pull to refresh
64
0
Александр @Dr_Logic

Пользователь

Send message
Race condition фактически есть, но реально, это надуманная проблема — если я с кем-то работаю в одной ветке — значит я много общаюсь с ними, постоянно делюсь кодом, обсуждаю архитектуру. Ничего не мешает договориться о моменте ребейза и зафризить ветку — это конечно хак за пределами SCM, но мне при работе в общей ветке не приходилось сталкиваться с race condition. Насчет того пропадет ли «гоночный» коммит при ребейзе — надо поставить эксперимент — в теории выглядит именно так, но надо бы убедиться — поэкспериментирую на досуге.
Дайте им ее почитать, вдруг они проникнутся. ;)
Git pull — rebase конечно не делает git pull и git rebase, так как git pull — это fetch & merge, а git pull --rebase — это fetch & rebase. Кроме того нужно понимать, что когда удаленная ветка ребейзена и вы делаете git pull --rebase базовый коммит — это не общий коммит в ветках feature и origin/feature, а первый незапушенный вами (то есть локальный) коммит. Линейка локальных коммитов, которая перемещается при git pull --rebase, легко конвертится в серию патчей, которые можно накатить, что бы с веткой не происходило — rebase, squash, такую серию патчей можно накатить куда угодно, поэтому я не понимаю, почему все так боятся ребейзить удаленные ветки.

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

Не надо придумывать никаких универсальных административных политик. Цель статьи — чтобы после прочтения стало понятно, как физически работает rebase в описанных ситуациях. Владея этим знанием нужно применять их по обстоятельствам, а не по своду каких-то магических методик. Если у меня 1 локальное изменение и я взял git pull и сижу правлю огромное количество конфликтов в коде, который я даже не трогал — что-то тут пошло не так, да? Наверно нужно откатиться и взять git pull --rebase.

Нет никаких солюшенов и сводов правил, есть вы и git, некий набор инструментов в рамках гита и ваше умение ими пользоваться.
Правда? Пока проблем не обнаружено. Со вторичными тематическими ветками не пробовал но шаренные ветки ребейзил. git pull --rebase вытягивает новую ветку и перемещает локальные коммиты наверх. Да и git help pull говорит:

--rebase
Rebase the current branch on top of the upstream branch after fetching. If there is a remote-tracking branch corresponding to the upstream branch and the upstream branch was rebased
since last fetched
, the rebase uses that information to avoid rebasing non-local changes.


Что намекает, что это допустимая ситуация. Возможно в более ранних версиях гита это был грязный трюк, но сейчас это вполне работает.
А вот еще классный вариант придумал — не делать фичу 3 пока не сделаны первые две. Сложно писать код на такой зыбкой почве как две динамично меняющиеся кодовые базы совместимость которых тестится только у меня в бранче. Ну и да декомпозиция задач 1 и 2 на более мелкие может облегчить этот процесс за счет того, что каждый этап занимает меньше времени и по сути делается в отдельной ветке (может с тем же названием, может «новая» ветка — продолжение отребейзенной старой)
У вас тут есть одно внутреннее противоречие из-за которого все проблемы:
— ветки 1 и 2 должны вестись изолировано
— ветка 3 должна содержать объединенные изменения из ветки 1 и 2.
Отсюда следует, что эти изменения не могут храниться в одних и тех же коммитах. Два выхода:
1. Либо изменения приезжают в ветку 3 с помощью мерджа и храняться в мердж-коммитах — запутываем граф.
2. Либо изменения из веток 1 и 2 дублируются в других коммитах — в ветке три — их можно переносить туда cherry-pick-ом, но тогда готовьтесь к конфликтам и дублированию пикнутых коммитов при интеграции ветки 3 в мастер, в который уже проинтегрированы ветки 1 и 2. Ну и черрипик не слишком быстрая операция так как предполагает много ручной работы.
3. Либо вам надо отказаться от полной изолированности ветки 1 и 2, то есть когда ветки 1 и 2 готовы к интеграции в ветку 3 они склеиваются ребейзом до текущего состояния (можно пометить его веткой release) и далее снова разрабатываются изолировано. Ветка 3 ребейзится на состояние release.

Третий вариант я не посчитал, так как он нарушает одно из входящих условий
Стойте, а код из ветки 1 в ветку 2 не может попадать? То есть изменения объединяются только в ветке 3?
Можно ли разбить фичи 1 и 2 на этапы? Например после завершения определенной работы в ветке 1 и 2 они готовы к вливанию в 3? В каком порядке фичи будут мерджиться в мастер заранее известно или по готовности? Может вам стоит пилить общий для всех этих 3 веток функционал в базовой ветке, относительно которой ребейзить все эти три фиче-ветки? И там уже тестировать перед вливанием в мастер?

Мне что-то то кажется что между вашими тремя ветками и мастером должна быть промежуточная ветка в которую вы вливаете изменения из этих трех.
Реально сложная задача, может она неправильно поставлена? Почему все три фичи не могут делаться в одной ветке если они так тесно взаимосвязаны?
Что мешает ребейзенную ветку влить в мастер merge-ем с опцией --no-ff? Выйдет тоже самое, не?
Да, тогда конечно squash тут не поможет не думал о такое ситуации.
Почитал про fixup, спасибо за наводку!
И пока вы работаете в ветке вы не переключаетесь на другую ветку? Или все-таки у вас БД столько же сколько веток (или она редко меняется, или изменения непротиворечащие). А зачем вам ветки в таком случае вообще? :)
Опять вы говорите о merge как об операции наложения изменений. Git merge тоже основан на merge. Git stash apply тоже основан на merge. Только споры обычно идут операции git merge, а точнее о том, стоит ли перед ней делать git rebase или нет. А еще о том, как подливать кодовую базу в тематическую ветку — через перебазирование самой ветки или через слияние изменений. Спасибо за интересную беседу anyway. У меня до ковыряния в сорцах гита еще не доходило.
Да не обязательно апи, схема бд может поменяться например, или у вас для каждой ветки своя БД развернута?
>> Исполнителю опять нужно идти и ребазировать-решать конфликты
А при мердже этого делать разве не надо в такой ситуации? :) Тут проблема не merge или rebase — проблема в самой ситуации. Код устаревает постоянно пока не влит в мастер. После вливания в мастер код заставляет устаревать другой код, еще не влитый в мастер. Это жизнь.
Большое спасибо за ссылку, к сожалею не могу сейчас почитать — отложил в закладки. Не пойму, почему на них нельзя откатиться? Можно. Код не будет работать? Да возможно. Семантический конфликт? Это за пределами системы контроля версий.

Теряется смысл контроля версий из-за семантического конфликта? А часто вы деплоите приложение из тематической ветки? :) Вы рассматриваете именно конфликтные ситуации — в случае если изменения в разных модулях например — то всего этого нет, так?

А семантический конфликт разве не возможен при обычном merge? Не было такого что после подливания мастера ваш код ломался? Ну там функцию в api выпили например в мастере. Rebase — физический уровень манипуляции коммитами, он не защищает и не провоцирует семантические конфликты.

То что теряется старая ветка легко поправимо — если после ребейза сломалась ветка, а вам надо срочно сделать демонстрацию заказчику — можно сделать git reset --hard на коммит E (на него указывает ORIG_HEAD и его можно увидеть в git log --all. Ребейз можно отложить. Я не говорю о том, что мол rebase — золотая пуля. Это просто инструмент который может быть полезен.

Если делать ребейз периодически то фикс семантики можно делать не только в конце — а деплоиться на промежуточные версии (на мой взгляд) бессмысленно. Смысл системы контроля версий на мой взгляд не теряется. И кстати а «посмотреть» разве не входит в задачи scm? Code review, например, провести вполне можно.

Все ваши утверждения верны, тут вопрос в отношении к этим фактам и стилю работы с кодом, а также задачами, которые в каждом конкретном случае вы ставите перед scm.
Прочитайте пожалуйста мой коммент. Очень надеюсь, что он поможет понять почему стрелки нарисованы именно так, а не иначе.
Это если трактовать стрелку как действие. Тут стрелки отображают структуру данных (ну вы наверняка в универе рисовали односвязные списки, можно считать, что это они).
Сорри, не убедили. Вырванный из контекста кусок кода мне, к сожалению, ничего не доказывает. do_recursive_merge — просто наложение изменений на дерево проекта (наложение диффа), про try_merge_command — не могу сказать про что, некогда ковырять. Я говорил о merge как о команде гита, которая создает коммит с двумя родителями. По вашей логике patch — тоже merge. Если вы это и имели ввиду — то ок, спор чисто терминологический и мы друг друга просто недопоняли.

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

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity