Git: rebase vs merge или линейная история против спагетти
От: vsb Казахстан  
Дата: 21.02.22 09:38
Оценка: 10 (2)
В Git есть два основных подхода к разработке:

Линейная история. История всегда линейна, никаких циклов в этом графе нет. При разработке ветки с новой фичей периодически делается rebase на main (или на test, если у вас отдельная ветка для разработки), ну или хотя бы перед тем, как отдать фичу на code review или слияние.

Большой плюс в том, что когда смотришь на историю main, то всё очень просто и понятно. Также удобно смотреть pull request-ы по коммитам.

У этого подхода я вижу два минуса:

1. rebase требует force push. Если зачем-то над этой веткой кто-то ещё работал, возникает хаос. Также теряются исходные коммиты, если при rebase была сделана ошибка, то её уже не исправить. Частично решается созданием новой ветки при каждом rebase-е, но тогда в репозитории будет множество веток, которые надо не забыть подчищать (и не перепутать при подчистке).

2. rebase это сложно для понимания и применения, UI при rebase менее очевидный, при разрешении конфликтов разработчик не видит своих будущих изменений.

Спагетти. Каждое изменение вносится в исходную ветку через merge. При визуализации разобраться в этом решительно невозможно.

Плюсы/минусы аналогичны минусам/плюсам выше.

Также у меня есть такое ощущение, что Git в целом больше заточен именно на подход с merge-ами. Это не технический аргумент, но я никогда не любил идти "против течения" и использовать инструмент не так, как его проектируют.

Каким подходом вы пользуетесь, как решаете проблемы (и считаете ли их проблемами)?
Re: Git: rebase vs merge или линейная история против спагетт
От: Muxa  
Дата: 21.02.22 10:09
Оценка: 22 (3) +1
vsb>1. rebase требует force push. Если зачем-то над этой веткой кто-то ещё работал, возникает хаос.
Не коммить в чужие ветки. Работаете над одной фичей — сделайте бранч для фичи и каждому разработчику отдельный бранч.

vsb>Также у меня есть такое ощущение, что Git в целом больше заточен именно на подход с merge-ами.

Нигде не встречал работу в мастер-бранчем через постоянные merge. Только rebase, PR, squash and merge.
Отредактировано 21.02.2022 11:14 Muxa . Предыдущая версия .
Re: Git: rebase vs merge или линейная история против спагетти
От: · Великобритания  
Дата: 21.02.22 10:14
Оценка: 21 (2) +1
Здравствуйте, vsb, Вы писали:

vsb>У этого подхода я вижу два минуса:

vsb>1. rebase требует force push. Если зачем-то над этой веткой кто-то ещё работал, возникает хаос. Также теряются исходные коммиты, если при rebase была сделана ошибка, то её уже не исправить. Частично решается созданием новой ветки при каждом rebase-е, но тогда в репозитории будет множество веток, которые надо не забыть подчищать (и не перепутать при подчистке).
Это хорошо работает в условиях короткоживущих веток. Если у тебя ветки маленькие, два-три коммита, живут два-три дня, то хаосу возникнуть в общем-то негде.
Если ветка большая, то ребейз лучше оставить на потом. Т.е. вначале толпой долго пилили, допилили, решили, что готово к мержу — договариваетесь, делаете ребейз, ещё раз всё проверяете каждый коммит и мержите.

vsb>2. rebase это сложно для понимания и применения, UI при rebase менее очевидный, при разрешении конфликтов разработчик не видит своих будущих изменений.

В IDEA сделали отличный UI для rebase.

vsb>Спагетти. Каждое изменение вносится в исходную ветку через merge. При визуализации разобраться в этом решительно невозможно.

Теоретически тулзы позволяют улучшить визуализацию. Например, скрыть мерж-коммиты.

vsb>Плюсы/минусы аналогичны минусам/плюсам выше.

vsb>Также у меня есть такое ощущение, что Git в целом больше заточен именно на подход с merge-ами. Это не технический аргумент, но я никогда не любил идти "против течения" и использовать инструмент не так, как его проектируют.
Как минимум, наличие довольно мощных rebase-команд в стандартной поставке самого git говорит об обратном.

vsb>Каким подходом вы пользуетесь, как решаете проблемы (и считаете ли их проблемами)?

В своих ветках ребейзю по полной, в том числе reword/fixup/squash/etc, каждый коммит стараюсь причесать. Если с кем-то работаю над некой веткой, то договариваюсь о стратегии с участниками.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Git: rebase vs merge или линейная история против спагетти
От: Bill Baklushi СССР  
Дата: 21.02.22 10:23
Оценка: +1
vsb:

vsb>В Git есть два основных подхода к разработке:

vsb>Линейная история. История всегда линейна, никаких циклов в этом графе нет.
В гите орграф и так без циклов. Насколько помню, разветвление и слияние в орграфах называется "гамак".
Модератор-националист Kerk преследует оппонентов по политическим мотивам.
Re: Git: rebase vs merge или линейная история против спагетти
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 21.02.22 10:46
Оценка: 16 (1)
Здравствуйте, vsb, Вы писали:

vsb>Каким подходом вы пользуетесь, как решаете проблемы (и считаете ли их проблемами)?


У нас trunck-based подход, т.е. через rebase, с отдельной веткой для каждой фичи. Да, если над фичей будет работать несколько человек, они рано или поздно что-то перетрут. При этом, если над фичей вынужденны работать несколько человек, значит была не верная декомпозиция задачи и фича слишком большая.

В целом я согласен, этот подход менее очевиден и несколько более сложен. Но это окупается за счёт получения простой и однозначной истории коммитов в мастере. Да и графический интерфейс ГитХаб(Лаб) частично компенсирует недостатки этого подхода, т.к. последнее слияние фича_ветка -> мастер делается не руками, а сервером Гит.
Re[2]: Git: rebase vs merge или линейная история против спагетти
От: Sharov Россия  
Дата: 21.02.22 11:14
Оценка:
Здравствуйте, Muxa, Вы писали:

vsb>>Также у меня есть такое ощущение, что Git в целом больше заточен именно на подход с merge-ами.

M>Нигде не встречал работу в мастер-бранчем через постоянные merge. Только PR + squash and merge.

PR+squash -- это типа склеить все коммиты в один? Т.е. merge будет из одного коммита? Почему не rebase тогда?
Кодом людям нужно помогать!
Re[2]: Git: rebase vs merge или линейная история против спагетти
От: Sharov Россия  
Дата: 21.02.22 11:15
Оценка:
Здравствуйте, ·, Вы писали:

vsb>>2. rebase это сложно для понимания и применения, UI при rebase менее очевидный, при разрешении конфликтов разработчик не видит своих будущих изменений.

·>В IDEA сделали отличный UI для rebase.

Я tortoise git(обновил до последней) регулярно путаюсь в rebase... На сколько там понятен merge, настолько непонятен
rebase...
Кодом людям нужно помогать!
Re[3]: Git: rebase vs merge или линейная история против спагетти
От: Muxa  
Дата: 21.02.22 11:17
Оценка: 6 (2)
S>PR+squash -- это типа склеить все коммиты в один? Т.е. merge будет из одного коммита?
Да

S>Почему не rebase тогда?

Rebase фича ветки делается перед PR.
Re[3]: Git: rebase vs merge или линейная история против спаг
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 21.02.22 11:47
Оценка: 11 (2)
Здравствуйте, Sharov, Вы писали:

S>Я tortoise git(обновил до последней) регулярно путаюсь в rebase... На сколько там понятен merge, настолько непонятен

S>rebase...

Я очень рекомендую прочитать Merging vs. Rebasing, в крайнем случае именно благодаря этой статье у меня в голове окончательно картинка сложилась.
Отредактировано 21.02.2022 11:49 kaa.python . Предыдущая версия . Еще …
Отредактировано 21.02.2022 11:48 kaa.python . Предыдущая версия .
Re[2]: Git: rebase vs merge или линейная история против спагетт
От: vsb Казахстан  
Дата: 21.02.22 11:49
Оценка:
Здравствуйте, Muxa, Вы писали:
M>Нигде не встречал работу в мастер-бранчем через постоянные merge. Только rebase, PR, squash and merge.

Случайно увидел при подборе монитора
Re: Git: rebase vs merge или линейная история против спагетти
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 21.02.22 12:08
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Также теряются исходные коммиты, если при rebase была сделана ошибка, то её уже не исправить. Частично решается созданием новой ветки при каждом rebase-е, но тогда в репозитории будет множество веток, которые надо не забыть подчищать (и не перепутать при подчистке).


Git ничего не теряет. До сборки мусора можно посмотреть и восстановить любую версию. См. команду show-ref.
Ce n'est que pour vous dire ce que je vous dis.
Re[2]: Git: rebase vs merge или линейная история против спагетти
От: vsb Казахстан  
Дата: 21.02.22 12:24
Оценка:
Здравствуйте, Don Reba, Вы писали:

vsb>>Также теряются исходные коммиты, если при rebase была сделана ошибка, то её уже не исправить. Частично решается созданием новой ветки при каждом rebase-е, но тогда в репозитории будет множество веток, которые надо не забыть подчищать (и не перепутать при подчистке).


DR>Git ничего не теряет. До сборки мусора можно посмотреть и восстановить любую версию. См. команду show-ref.


Ну в теории да, но это уже больше похоже на восстановление удалённого с диска файла.
Re: Git: rebase vs merge или линейная история против спагетти
От: · Великобритания  
Дата: 21.02.22 13:16
Оценка: +1
Здравствуйте, vsb, Вы писали:

vsb>Также у меня есть такое ощущение, что Git в целом больше заточен именно на подход с merge-ами. Это не технический аргумент, но я никогда не любил идти "против течения" и использовать инструмент не так, как его проектируют.

Кстати. Если подумать, то мерж по большому счёту немного про другое. Это когда у тебя сложный продукт со множеством поддерживаемых версий. Т.е. обнаружили багу в JDK, выяснили, что она тянется аж с java8. Пофиксили в java8, а потом это всё замержили и в java11, 17 и master.
А типичный проект с одной веткой и release-тегами... там rebase — то что доктор прописал.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: Git: rebase vs merge или линейная история против спагетти
От: vsb Казахстан  
Дата: 21.02.22 13:25
Оценка: +1
Здравствуйте, ·, Вы писали:

vsb>>Также у меня есть такое ощущение, что Git в целом больше заточен именно на подход с merge-ами. Это не технический аргумент, но я никогда не любил идти "против течения" и использовать инструмент не так, как его проектируют.

·>Кстати. Если подумать, то мерж по большому счёту немного про другое. Это когда у тебя сложный продукт со множеством поддерживаемых версий. Т.е. обнаружили багу в JDK, выяснили, что она тянется аж с java8. Пофиксили в java8, а потом это всё замержили и в java11, 17 и master.

На мой взгляд это через cherry picking правильней делается. А куда тут мердж засунуть, я вообще не представляю.
Re: Git: rebase vs merge или линейная история против спагетти
От: halo Украина  
Дата: 21.02.22 14:02
Оценка: 5 (1)
Здравствуйте, vsb, Вы писали:

vsb>1. rebase требует force push. Если зачем-то над этой веткой кто-то ещё работал, возникает хаос.

В случае с "кем-то ещё" есть git push --force-with-lease, более безопасный чем git push --force. Ну и к тому же, git fetch -p @{U} и там уже смотреть что делать с изменениями с удалённого репозитория (иногда эти изменения -- твои).

vsb>Также теряются исходные коммиты, если при rebase была сделана ошибка, то её уже не исправить. Частично решается созданием новой ветки при каждом rebase-е, но тогда в репозитории будет множество веток, которые надо не забыть подчищать (и не перепутать при подчистке).

Нет, есть git reflog, умеет отмирать со временем сам, или принудительно -- с помощью git gc. Вот что в git не залетает в историю, так это индекс, который можно случайно грохнуть git reset --hard.

vsb>если при rebase была сделана ошибка, то её уже не исправить

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

vsb>2. rebase это сложно для понимания и применения, UI при rebase менее очевидный, при разрешении конфликтов разработчик не видит своих будущих изменений.

vsb>rebase это сложно для понимания
Нет, совершенно. Это просто git reset на определённый коммит и git cherry-pick на стероидах.
vsb>rebase это сложно для ... применения
В некоторых случаях -- может быть. Например, если на topic-ветке затеяли рефакторинг, то тогда, скорее всего, придётся подчищать каждый коммит. Или, например, если от topic-ветки растут ещё ветки. Тогда приходится делать git rebase для каждой ветки отдельно в правильном порядке, так как git совершенно безразлично что на что перебазировать. Я когда-то писал для этого скрипты, умеющие такой rebase автоматизировать, но чем меньше сущностей -- тем проще + не нужно тянуть за собой свой набор скриптов на каждую машину.
vsb>при разрешении конфликтов разработчик не видит своих будущих изменений
Смотря куда смотрит. Для этого есть как минимум git log --left-right @{U}...{U} (с троеточием), и добавление маркеров в commit message (если на проекте есть такое соглашение), и git trailers, и настройка $PS1 в bash (у меня, например, всегда видно количество изменений локально и с удалённого репозитория, если topic-ветка и её upstream-ветка указывают на разные фиксации). И это только перед началом rebase. Во время самого git rebase возможны другие техники.

vsb>Каким подходом вы пользуетесь, как решаете проблемы (и считаете ли их проблемами)?

* внедрение изменений с родительской ветки на topic-ветку — git rebase локально.
* внедрение изменений с topic-ветки на родительскую — git merge --no-ff --no-squash (локально или удалённо, зависит от того, как в неё принимаются изменения) после предварительного git rebase topic-ветки.

vsb>Также у меня есть такое ощущение, что Git в целом больше заточен именно на подход с merge-ами. Это не технический аргумент, но я никогда не любил идти "против течения" и использовать инструмент не так, как его проектируют.

Мне кажется, что git вообще ни на что не был изначально заточен. Это действительно stupid content tracker. Вот Mercurial заточен на merge, там rebase не привествуется вообще, и, если не ошибаюсь, по умолчанию даже не доступен, и позже пресекается public-фазами коммитов.
Re[3]: Git: rebase vs merge или линейная история против спагетти
От: · Великобритания  
Дата: 21.02.22 14:02
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>·>Кстати. Если подумать, то мерж по большому счёту немного про другое. Это когда у тебя сложный продукт со множеством поддерживаемых версий. Т.е. обнаружили багу в JDK, выяснили, что она тянется аж с java8. Пофиксили в java8, а потом это всё замержили и в java11, 17 и master.

vsb>На мой взгляд это через cherry picking правильней делается.
Нет, конечно. cherry-picking обычно нужен для бэкпортов. Например, поправили багу в 17й версии. Вылез клиент, сидящий на версии 8, не желающий переезжать на 17ю, но готовый заплатить за фикс этой баги. Вот для него зачеррипикаем те фиксы, которые он хочет поверх версии на которой он сидит.

vsb>А куда тут мердж засунуть, я вообще не представляю.

Все ожидают, что 17я версия содержит всё что есть в 8й, значит 17я — потомок 8й. Иными словами, все коммиты в 8й мержатся в 17ю.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Git: rebase vs merge или линейная история против спагетти
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 21.02.22 14:55
Оценка:
Здравствуйте, ·, Вы писали:

vsb>>·>Кстати. Если подумать, то мерж по большому счёту немного про другое. Это когда у тебя сложный продукт со множеством поддерживаемых версий. Т.е. обнаружили багу в JDK, выяснили, что она тянется аж с java8. Пофиксили в java8, а потом это всё замержили и в java11, 17 и master.


Не получится замержить, код сильно разный.

vsb>>На мой взгляд это через cherry picking правильней делается.

·>Нет, конечно.

Да, конечно.

·> cherry-picking обычно нужен для бэкпортов. Например, поправили багу в 17й версии. Вылез клиент, сидящий на версии 8, не желающий переезжать на 17ю, но готовый заплатить за фикс этой баги. Вот для него зачеррипикаем те фиксы, которые он хочет поверх версии на которой он сидит.


А могли начать фиксить в 8-й и черипиками доползти вверх до 17-й. Разницы по сути никакой.

vsb>>А куда тут мердж засунуть, я вообще не представляю.

·>Все ожидают, что 17я версия содержит всё что есть в 8й, значит 17я — потомок 8й. Иными словами, все коммиты в 8й мержатся в 17ю.

Нет, может быть много специфики, которая в 17-й просто нафиг не нужна (например, подсистема переделана и проблемы нет уже в принципе).
The God is real, unless declared integer.
Re[3]: Git: rebase vs merge или линейная история против спагетт
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 21.02.22 14:57
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, Muxa, Вы писали:

M>>Нигде не встречал работу в мастер-бранчем через постоянные merge. Только rebase, PR, squash and merge.

vsb>Случайно увидел при подборе монитора


Нормально. У нас до 6 видимых таким образом веток дорастало без проблем и заметных последствий.
The God is real, unless declared integer.
Re[5]: Git: rebase vs merge или линейная история против спагетти
От: · Великобритания  
Дата: 21.02.22 16:11
Оценка:
Здравствуйте, netch80, Вы писали:

vsb>>>·>Кстати. Если подумать, то мерж по большому счёту немного про другое. Это когда у тебя сложный продукт со множеством поддерживаемых версий. Т.е. обнаружили багу в JDK, выяснили, что она тянется аж с java8. Пофиксили в java8, а потом это всё замержили и в java11, 17 и master.

N>Не получится замержить, код сильно разный.
_Если_ будет конфликт — зарезолвим. В этом и суть мержей — сливать разный код и разрешать конфликты если сильно разный.

N>·> cherry-picking обычно нужен для бэкпортов. Например, поправили багу в 17й версии. Вылез клиент, сидящий на версии 8, не желающий переезжать на 17ю, но готовый заплатить за фикс этой баги. Вот для него зачеррипикаем те фиксы, которые он хочет поверх версии на которой он сидит.

N>А могли начать фиксить в 8-й и черипиками доползти вверх до 17-й. Разницы по сути никакой.
Разница в графе истории. Так у тебя две навечно разъехавшиеся ветки, сравнить которые нет никакой возможности. А если в графе настоящие мержи, то всё как на ладони.

vsb>>>А куда тут мердж засунуть, я вообще не представляю.

N>·>Все ожидают, что 17я версия содержит всё что есть в 8й, значит 17я — потомок 8й. Иными словами, все коммиты в 8й мержатся в 17ю.
N>Нет, может быть много специфики, которая в 17-й просто нафиг не нужна (например, подсистема переделана и проблемы нет уже в принципе).
Тогда будет пустой мерж. В графе истории зафиксируется явная запись о том, что "подсистема переделана, проблема больше не актуальна". Вместо "а хз, вася вроде смотрел год назад, и вроде бы что-то пофиксил в каком-то из бранчей, надо бы в почте покопаться...".
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Git: rebase vs merge или линейная история против спагетти
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 21.02.22 16:12
Оценка: 4 (1)
Здравствуйте, vsb, Вы писали:

vsb>Каким подходом вы пользуетесь, как решаете проблемы (и считаете ли их проблемами)?


Оба варианта абсолютизируют крайние формы. Неумеренность тут вредна.

Действительно, линейная история удобнее тем, что на каждом мерже
1) Понятно, откуда пришло изменение: сам мерж может в принципе содержать нечто, чего не было исходно ни в одном родителе;
2) Родительские коммиты, корректные по отдельности, могут конфликтовать. Об этом часто забывают, не проверяя результаты мержа.
Результаты мержа должны проверяться — через CI в идеале на каждый коммит, или хотя бы регулярно с адекватной частотой (типа, раз в сутки).

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

Но требование тотальной линеаризации плохо, с другой стороны, тем, что вызывает много конфликтов там, где их в принципе не может быть (разные люди пилят разные неперекающиеся части — ну например одна команда оптимизирует SQL индексы, другая чинит JSON схемы. Зачем их форсировать делать что-то по порядку и подгоняться под чужое?

На прошлой работе это выглядело так:

1. Сервер — Gerrit — умеет удобно работать с цепочками коммитов и с их версиями (можно переделывать по многу раз и сравнивать версии диффами), и допускать только по прохождению peer review и одобрения от CI.

Он не рассчитан на git-flow (не разрешает просто так делать 100500 частных веток), но позволяет делать неименованные (нумерованные) ветки конкретных подцепочек коммитов (1 или больше).

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

2. У большинства реп выставлен режим: сервер делает мержи, но не принимает их от юзеров. (Можно было бы и принимать, но проще так.)
Сервер, если видит контекстный конфликт, отказывает в мерже, тогда надо делать rebase.
Рекомендуется линеаризовать по максимуму.
Мержи могут давать проблемные версии. Лечится это своевременным обнаружением (CI запуски по крону), ручной проверкой, когда надо, и замораживанием изменений в релизных ветках.

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

3. У некоторых с особо сложными, но нечастыми отдельными изменениями — всё наоборот: запрещены мержи самим сервером, но разрешено принимать их от юзеров.
Вот они умудряются делать мержи между релизными ветками.

По-моему, это был очень симпатичный вариант как организовывать совместную работу.
The God is real, unless declared integer.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.