Beware: git(hub)+git+subversion= many epic fails...

Вынужден с огорчением признать, что такая вот схема:

GitHub  локальный git  SVN-репозиторий
оказалась нежизнеспособной, хотя изначально не казалась таковой.

У меня это, правда, осложнялось тем, что в SVN-е запомнена долгая и трудная жизнь, а на GitHub я поэкспортил только /trunk/, только одного проекта, да и то не весь, а только начиная с публичных версий.

В результате, пока SVN-жизнь идет только в /trunk/libraw, все хорошо, синхронизируемся, в обе стороны, почти без лишнего секса.

А вот как только версия в SVN инкрементится, не затрагивая синхронизированную часть (в /tags/ что-то покоммитили или в другой проект), то git-svn сносит крышу, возникают попытки повторного наката старых диффов, оттуда конфликты и все такое.

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

Короче, достало!

Скорее всего, я это место просто неправильно готовлю, но за две недели упражнений правильного рецепта так и не нашел.

В-общем, оказалось проще SVN из этого супа удалить. В git, понятное дело, остались только те самые, показанные на GitHub, публичные версии, исчезновение проблем может быть и с этим связано.

И понятно в чем идеологическая проблема. В том что git svn rebase есть, а git svn pull - нету.

P.S. А вообще, git - прикольный. GitHub - тоже. P.P.S. А merge там - непривычный (привыкшему к cvs update -j rev1 -j rev2), но если наморщить ум и понять как оно теперь, то просто волшебный.

Comments

Подозрительно это, мы тут поддерживаем свои ветки в git нескольких больших проектов, которые живут в SVN. Оно живет, даже с ветками

В чистом виде с SVN проблем никаких нет.

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

Идеологически, как я понимаю, проблема в том что
git pull remote-git
git svn rebase remote-svn

Что б небыло такого запутанного графа проекта надо делать git fetch origin; git rebase origin/master и история будет линейной, но это в pure git, не уверен будет ли такое работать с svn.

Ну в моем случае бранчи из SVN не видны (не импортировались).

Но я скорее о том, что two-way (точнее, three-way, по числу репозиториев) в случае разницы идеологий - проблемная вещь.

svn - кака.
это было ясно ещё со времён, когда cvs уже надоел,
а базара и жита ешё не было.
Удивильно, сколько народа на svn подсело и слезать не хотят.

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

SVN - вовсе не система контроля версий кода, а "версионная FS". Хотя, если бы в ней были бы *нормальные* теги (как в CVS или Git), жить можно было бы и с ней. Без тегов, конечно, поразительно неудобно. Но зато энтерпрайз на всю голову, бэкапы, модуль к апачу, ACL хоть какие-то.

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

> svn ... энтерпрайз на всю голову, бэкапы, модуль к апачу, ACL хоть какие-то.

wtf enterprise? что там такого особенного? крутой лейбл "сделано для толстых"?

бэкапы - бэкапьте чем хотите и/или пушайте на другие зеркала.
модуль к апачу - ну есть какие-то, зачем они, кроме просмотра?
acl - gitolite обеспечивает, на branch, каталог и ещё чего-то там...

Да, да, да! holy war!!!!

Я обоими путями относительно недавно ходил (git-ом сегодня, svn-ом - летом) разницу вижу.

Основная разница в том, что git не предназначен для удобного управления несколькими проектами в одном репозитории. Идеологическая проблема - это общее пространство тегов/бранчей. Сабмодули - это костыль.

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

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

При этом в рамках одного проекта git мне нравится больше. Ну и теги, теги! Если бы в SVN это место не было бы профукано полностью, жизнь была бы сильно лучше, конечно.

И понятно в чем идеологическая проблема. В том что git svn rebase есть, а git svn pull - нету.

ну так
1. git svn rebase - это git svn fetch + git rebase ...
2. git svn pull - это git svn fetch + git merge

по-идеи можно использовать и второе, просто в remotes/git-svn тогда пойдут не все ваши коммиты в master, а только один, который merge.

Я подробности уже забыл, больше полугода прошло, но что схема "github - локальный git - svn-repo" с коммитами везде (и гитхаб и Svn) и мержем на локальном git оказалась нежизнеспособной - запомнил надолго.

локальный git - svn - работает и так многие живут.

ясно.
а я вот тоже перешёл на git local<->svn remote.
и тоже только trunk вытащил (на одном уровне с trunk есть ещё releases, который по смыслу является tag'ом..). интересно, осталась ли проблема, когда commit'ы идут не в trunk...

По мне, так SVN-овские теги/бранчи - это один сплошной фейл. Это после 15+ лет использования CVS и с осени - с гитом.
И это место обязательно поимеет, уж найдет способ.

git конкретно рулит как система управления сорцами одного проекта (с несколькими связанными - хуже), хотя конечно git over http(s) - тоже не подарок, очень медленно. Но может я его как-то не так готовлю.

Ну и github, да, рулит.

Мне git очень нравится, даже только как local для удалённого svn.

На счёт управления несколькими проектами - хз, сам не пробовал. Читал про несколько вариантов - submodule's, и что-то с subtree, вроде ничего критичного - но хз как оно на деле.
Особенно учитывая то, что в текущем проекте, в котором я работаю, люди руками merge'ат файлы из дочерних проектов в главный (ну конечно не совсем руками, с помощью тулзы типа merge - но смысл не меняется).
Собирал ParaView, в котором есть submodule's - вроде всё норм.

То что мне не нравиться:
1) в силу того, что ветка это всего лишь указатель на коммит с именем, и обычно после мержа этот указатель удаляется, не остаётся никакой истории что это ветка началась тут, закончилась тут - просто цепочка комитов. Точно также если удалить несмердженную ветку - то все коммиты пропадают, как будто их и небыло
2) то же самое касается и rebase'а - сделали rebase, но в истории это никак не отображается
можно конечно для 1) и 2) помечать коммиты тэгами, но всё равно факт того, что часть информации о движениях может быть потеряна навсегда напрягает. Грубо говоря можно "случайно" грохнуть весь репозиторий и не останется никакой истории.
3) Выкачивал svn репозиторий с ~5000 коммитов - было долго, что-то около 10 часов. знаю что можно качать только часть ревизий, но хотелось бы иметь всю историю, тем более git с ней шустро работает. Это даже не минус самого git'а - тут ничего не поделать. Также были какие-то глюки(error'ы при fetch'е), которые вылечились убийством процессов TSVNCache и TGITCache.
4) я использую msysgit - он _/внезапно/_ не поддерживает длинные пути - лечится "subst g: ." . но тоже, это не проблема самого git'а

История как-то хранится, иначе бы последовательные rebase или merge портились бы.

А в остальном, да, отстрелить себе ногу несложно. Но так мы и команду rm запретим, она тоже стирает все нахрен, а это опасно!

История как-то хранится, иначе бы последовательные rebase или merge портились бы.

не понял про последовательные rebase и merge.

А в остальном, да, отстрелить себе ногу несложно. Но так мы и команду rm запретим, она тоже стирает все нахрен, а это опасно!
Я хочу чтобы действуя по правилам VCS, вся история сохранялась бы - если сказал грохнуть всё, пусть хранит информацию о том что в этот момент всё грохнулось, и можно начать с чистого листа, но информация о старых состояниях пусть всё же где-то внутрях хранится. Я не против чтобы допустим были чисто административные команды, которые могут удалять куски истории безвозвратно, но пусть это не выносится на user-level.
Как дела в SVN-е с ветками (никогда в нём ветки не использовал) - если грохнуть ветку, ведь история всё же останется? Будет ведь просто запись об удалении в новой ревизии?
Я понимаю что для поддержки такой истории в git придётся что-то переделывать, добавлять новую модель/логику сохранения истории - и наверняка этого делать не будут - но факт ведь остаётся..

Про последовательные merge на примере libraw:
- есть ветка master где разработка на основе dcraw.c (откуда используется много кода, но сильно попатченного)
- есть ветка vendor-branch, куда кладется оригинальный dcraw.c (раз в несколько месяцев выходит новая версия).

Ну вот я в мастере говорю git merge vendor-branch и импортируются только те изменения, которые были с прошлого merge.

Касаемо хранения всей истории: git предполагает, что ветки создаются легко, дешево и на каждый чих (merge отличный, почему бы нет).
Если бы их нельзя было бы удалять, у меня их были бы уже десятки, если не сотни. Ну а нахрена они мне, если стандартный паттерн предполагается такой:
git branch feature
git checkout feature
подевелопили, потестировали - работает
git commit && git checkout master && git merge feature
И после этого ветка feature нафиг не нужна.

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

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

Ну и нафига 20 коммитов тащить в общий репозиторий, если их можно rebase -i в один ("добавлена, протестирована и документирована фича 8") и уже в виде одного коммита push-ить.

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

Не, это понятно.
Я вот только вместо rebase, merge'у в ветку, которая потом пушится в удалённую. Главное --no-ff написать, тогда в 'общей' ветке будет один merge-commit, а не перемотка(когда возможно).


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

Я предпочитаю иметь и то, и то. Пусть даже серию мелких коммитов только локально.
Вот накодил что-то - закомитил, показалось дико убогим - удалил, сделал коммит, переписал - закомитил, смёржил с "общей" веткой.
Через год внезапно то, что казалось убогим, захотелось снова поковырять - ихмо это один из тех пунктов, для которых vcs и предназначенно..

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

Ну так заведите репозиторий "всякая хрень" и push-те туда все свои бранчи, проблем то. А в рабочем (и, особенно, общекомпанейском т.е. "центральном") держите только чистовые варианты.

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

Я согласен, что рабочее место должно быть прибрано - хоть и пришёл к этому опытным путём. Когда реально видишь результаты этой аккуратности, начинаешь особенно её ценить.

Но заводить отдельный репоизторий для мелких коммитов не считаю необходимым. Мелкие feature/topic-branch'и мерджатся одним коммитом в стволовые ветки - и после не мешаются.
Если же речь идёт о том, что в перспективе локальный репозиторий может использоваться ещё кем-то (всмысле с него будут fetch'ить), то да, скелетов можно спрятать в шкаф. Только я бы работал в шкафу (опять же, я не думаю что мелкие topic-ветки будут хоть как-то мешать), и из него пушил бы в чистовой локальный, а из него в удалённый.

кстати, вот эти чуваки кричат что наоборот, не надо прятать скелетов - http://www.youtube.com/watch?v=0SARbwvhupQ .

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

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

- пространство бранчей должно быть обозримым. Т.е. это максимум - экран (24 строки), а оптимум вообще меньше десятка (5-8).
Я не говорю, что не нужно удалять смерженные бранчи. Их можно спокойно удалять (git branch -d (именно маленькая d - для смёрженных бранчей)) - "мелкие" коммиты из бранчи останутся, а сама бранч нет (как я понял, чтобы всё-таки увидеть её, надо лезть в reflog).
Или вы говорите про удаление так же самих коммитов ветки?
- то же самое с тегами.
На счёт тэгов - это да. По-идеи в моём подходе, надо тэг-ать некоторые коммиты feature-веток. Можно конечно придумать таким тэгам разные префиксы и фильтровать их при выводе - но понятно, кому как нравиться.. кому-то фильтровать тэги, кому-то держать их в отдельном репозитории.

Да, и про удаление (объединение) коммитов и про удаление нахрен неудачных форм эволюции. Если эти формы в чем-то могут быть интересны - в архив их. И забыть навсегда: возвраты к экспериментальному коду годовалой давности если и бывают, то единичные.

Мой опыт состоит в том, что в архив приходится ходить черезвычайно редко. Ближе к никогда.

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

> Ну и нафига 20 коммитов тащить в общий репозиторий, если их можно rebase -i в один

Извиняюсь, что встреваю. Но может хоть здесь пошлют в правильном направлении.
Везде пишут про rebase.
Вот сколько не пытался понять rebase столько у меня и не получалось. Все время он меня пугает и устает. Где бы для солдат и матросов про него прочитать? Манил, гоглил. Понял, что тупой.
В результате пришел к другому, чуть более для меня понятному:

git checkout -b featureBv2 origin/master
git merge --no-commit --squash featureB
поправили конфликты, еше чего то сделали
git commit

А далее уже push или чего еще. Интересно это просто еще один способ достигнуть желаемого результата или чтото в нем есть глубоко порочное?

Представь, что у тебя в руках стопка тарелок, и на сервере (origin) стопка тарелок.
git rebase origin/master - значит что стопка на сервера берется за основание и пытается привести к тому виду которое у тебя на руках.
То есть после этой операции ты имеешь origin/master + delta, где дельта твои коммиты (если предположим, что коммитил ты один).
После этой операции можно спокойно пушать. rebase также убирает ненужные коммиты типа merge commit.

Я например обхожусь без мержа.

git checkout -b featureBv2
git commit
git push origin featureBv2:master

если кто то до меня пушнул нужно сделать так:
git fetch origin
git rebase origin/master - это приведет к тому что мой коммит "всплывет" в истории наверх даже если был сделать до последних изменений в мастере
git push origin featureBv2:master

Пример про тарелки имхо как-то не очевиден.
Можно воспринимать это так:
после pull'а, последний коммит в ветке, у вас в локальном репозитории и в удаёлнном, один и тот же.
И у вас и у сервера, после этого коммита, может быть бурная разработка, из-за чего ваши пути расходятся, то есть origin/master это отдельная ветка, и master это тоже отдельная ветка. то есть это уже разные ветки, с общим предком.
После pull'а, в общем случае вы ответвляетесь от удалённой ветки. То есть rule of thumb - сделали pull, начали работу - значит вы уже отбранчевались от удалённого repo.
Когда вы хотите поделится с удалённым репозиторием своими изменениями, основными вариантами являются:
1. смерджить вашу ветку и удалённую. то есть merge
2. взять вашу ветку за то место, в котором произошло разветвление, отрезать в этом месте и прилипить к голове удалённой ветки. то есть rebase

Вот уже и не знаю куда отвечать.
СПАСИБО!!!
Внимательно следил за вашей с J0hn дискуссией и боялся прервать. Наконец то стало проясняться про rebase и прочие нюансы и usecsae-ы.
Тупой окончательный вопрос про rebase (для себя):
Есть CMakeLists.txt и в нем допустим строка:

clahe equalizer highpass hotpixels lowlight

мы вдвоем с живчиком сделали pull, чего то там натворили, поправили CMakeLists.txt
живчик:

clahe equalizer highpass hotpixels lowlight nlmeans

я:

clahe equalizer highpass hotpixels lowlight density

Живчик успел push раньше.
я делаю pull и rebase
1) у меня случится конфликт? или втихомолку внесутся мои изменения, потеряв изменения живчика?
2) а если мы одновременно пушить начали (что конечно маловероятно). Кто последний, того и тапочки? По идее конфликт должен случиться и я думаю будет.

Можно коротко. Я уже почти достиг просветления на данном этапе.

Так как диффы - всегда на уровне строк, то конфликт обязательно будет.

Так как пушатся (и вообще коммитятся) не отдельные файлы, а changeset-ы (не вдавался, как это в git называется), значит там возникает блокировка (на проект?) и второй не успеет.

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

Я так щетаю.

Я лишь добавлю что гит скажет при пуше второго, что fast forward невозможен. Это значить что нужно сделать пулл и ребэйз. Но.
git pull это тоже самое что и

git fetch
git merge

Мы рекомендуем git pull не делать, иначе гит будет мержить локальный коммит с тем что свалилось с сервера. Можно так
git pull --rebase тогда это будет эквивалентно:
master> git fetch
master> git rebase origin/master

Как уже сказал lexa второй получит конфликт при rebase, и нужно будет его решит прежде чем продолжить. Потом можно делать пуш.

Спасибо.
Приятно наконец то почуствовать себя не полным идиотом. :-)

Я вот когда начал git изучать, сначала искал QuickRefernce, типа основные команды посмотреть - ничего доступного для бысторого вьезжания сходу не нашёл. Потом начал смотреть краткие статьи с описанием - то что я видел, всё написано сумбурно и полно горячей мочи от восторгов. Особенно умиляют советы типа, для лучшего понимания нужно изучить структуру данных git'а - вот это вообще пипец.
Далее нашёл какое-то руководство(может даже с kernel.org, но могу ошибаться - читал с телефона) - там те же саки.
В итоге набрёл на вменяемое руководство-книгу Pro Git, которая есть и на русском, на английском, и на других языках. Вот собственно - http://progit.org/book/ru/ , первых трёх глав должно хватить для начала.
Конкретно про rebase - http://progit.org/book/ru/ch3-6.html .
Есть описание ещё тут http://kernel.org/pub/software/scm/git/docs/git-rebase.html , особенно иллюстративен пример где есть master, next, topic:
изначально:

o---o---o---o---o master
\
o--o--o--o--o next
\
o---o---o topic

делаем git rebase --onto master next topic, получаем:

o---o---o---o---o master
| \
| o'--o'--o' topic
\
o--o--o--o--o next

-----
Для сплющивания нескольких коммитов, в один, я rebase не использую, так как считаю идеологически неверным - зачем терять инфу? merge сделает тоже самое сплющивание, да ещё и сама цепочка коммитов останется.
rebase я использую в следующем контексте:
- есть проект
- перед непосредственно работой, нужно выполнить некоторые настройки системы автосборки - для этого я завёл отдельную ветку - BuildConf (можно вынести все файлы настройки в не версифицируемую область, то есть как советует svn иметь conf.template, и каждый разрабочик копирует в сonf, и правит уже его. но зато так, я получу историю своей настройки сборки проекта)
- feature-ветки я ответвляю от BuildConf
- когда feature ветка готова, и должна смёржится в master, я её снимаю с головы BuildConf и сажаю на master (то есть rebase), а потом мёржу в master (с опцией -no-ff, чтобы всегда merge'ем был один коммит). Это для того, чтобы настройки BuildConf не попали в master.
- после merge'а feature, master ушёл вперёд от разветвления с BuildConf, если для работы над следующей feature в рабочем дереве должны быть изменения от предыдущей feature, то просто пересаживаю BuildConf на голову master (то есть опять rebase).
- если во время работы над очередной фишкой, нужно поменять конфигурацию сборки, то есть сделать в неё коммит с изменениями, то feature пересаживается на новую голову BuildConf (опять rebase)

Когда 20 обезъян тащут в главную ветку миллион своих коммитов, получается свалка. И есть очень даже большой смысл это все чистить. Полезность информации о нескольких патчах сомнительна.
К тому же там получается засада с теми мержами в которых были конфликты и которые твои коллеги успешно решили но посколько использовали merge то в некоторых случаях при rebase тебе прейдется делать то что делали они. Вообщем геморрой один.

ээ, я какбы говорил о том, что в master, от всей моей бурной работы в ветке feature, отразится только один merge-commit

Ну граф истории будет напоминать вот такой
http://www.viget.com/uploads/image/merge_commits.jpg
если работаешь один или вдвоем. Если людей поболе то конечно и проблем с этим будет поболе :)

мы видимо о разном говорим.
У меня вообще, в удалённом repo, только одна ветка - trunk, это вообще svn.
Там всё линейно, хотя и merge'у у себя ветки.
Пушить локальные ветки никто не заставляет.
Нужна линейная история в локальном repo, смотрите только на стволовые ветки. Если напрягают feature ветки в локальном repo, сделайте ещё один локальный. один из них будет чистовой, только со стволовыми ветками, другой со скелетами в шкафу, тут это уже обсуждалось.

Аааа, речь все еще об git-svn? Я думал мы уже просто про гит говорим :)

для git это также справедливо. про git-svn сказал, чтобы подчеркнуть.
Если вы будете пушить только master, ваши локальные ветки будут только у вас, как бы rtfm

В mastere будут merge commity. Ну посмотри на картинку. при чем тут бранчи я не понял.

Я смотрел, что это за ветки, я не пойму - где они? локально или в центральном repo?
сколько в центральном repo всего веток, какое их предназначение..

Ну вот а советуешь мануал читать мне :)
Это все в одной ветке/branch. когда используешь git merge гит создает коммит которые в логе выглядит вот так:

commit a0b46a7c57e37f5dc43373ba9167ad2da32c1ec5
Merge: c2d8046... 73e0e15...
Author: Fred Bloggs
Date: Tue Jun 17 17:30:49 2008 +0100

Merge branch 'master' into new_feature

gitk, и другие визуализаторы истории показывают историю как на той картинке. Без такого графа вообще иногда не понятно что смержили, откуда и зачем. Бранчи тут не причем.
Возможно в git-svn эта информация теряется и все не выглядит так плохо.

http://www.kerrybuckley.org/2008/06/18/avoiding-merge-commits-in-git/

о блин, сейчас поигрался с несколькими репозиториями - действительно, push коммитет и смёрженную ветку тоже - rtfm мне.
Интересно, может есть опция, которая будет коммитеть только merge-commit'ы, а не все ветвления.
Но rebase это workaround, а не решение проблемы. нужен dcommit для git'всих репозиториев..

git merge --squash - но это опять workaround, так как графа мержа нет.

причём вроде то что я хочу, не вписывается вообще в текущию модель git - как я понял это связанно с хэшированием родительских хэшей.
Реально как-то гадко получается - merge дурацкий, rebase в этом случае вообще workaround, а главное что одна из рекламируемых фич git'а это легковесные локальные ветки, которые как оказываются в стандартных work-flow'ах (когда ветка мержится в публичную ветку) вообще не локальные.

Ну граф истории будет напоминать вот такой
http://www.viget.com/uploads/image/merge_commits.jpg
если работаешь один или вдвоем. Если людей поболе то конечно и проблем с этим будет поболе :)

Ещё, раз, что именно это за граф? Какоей именно там workflow? это не похоже на то, когда все merge'ат feature барнчи в главную

Почитай вот этого товарища, тут еще с картинками, он объясняет почему образуются merge commitы и как их убрать.
http://lostechies.com/joshuaflanagan/2010/09/03/use-gitk-to-understand-g...

То есть если вы мержите _и_ ребейзите, то столько ветвлений не будет, будет прямая. Если мержить без ребейза, будут такие рельсы.

почему образуются - это понятно,
понятно что если делать rebase, и merge с -ff (то есть просто merge) то будет fastforward.
Я конкретно спрашивал про ту картинку - там ветки merge'атся, не только в одну, но и в друг друга - что это за workflow?

Это отсюда:
http://www.viget.com/extend/only-you-can-prevent-git-merge-commits/
Но я подобные картинки видел везде. Если просто мержить, то будет нечно вроде такого.

Что вы хотели показать этой картинкой:

1 То что merge-commit's это вообще плохо?

2.Или то что merge'ить (через merge-commit) feature-ветки в master это плохо?

Для иллюстрации 2. картинка не подходит, так как там ветки вливаются не только в master, но и между собой - что именно там происходило, вы так и не объяснили

* 1 То что merge-commit's это вообще плохо? *

Да.

* 2.Или то что merge'ить (через merge-commit) feature-ветки в master это плохо? *

В этом вообще смысла нет (ну то есть для вас похоже есть, если хотите оставить информацию о том где бранч был сделан и куда он смержился)
prompt [featureB]>git push origin HEAD:master

или если какой то шустрик до нас запушил:

prompt [featureB]>git fetch origin
prompt [featureB]>git rebase origin/master
prompt [featureB]>git push origin HEAD:master

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

merge тут вообще не нужен.

* 1 То что merge-commit's это вообще плохо? *
Да.

Ну а как без них нормально организовать что-то чуть более сложнее одной стволовой ветки, например http://habrahabr.ru/blogs/Git/106912/ ?

или если какой то шустрик до нас запушил:

я такой rebase делаю, но merge'у с --no-ff, специально, чтобы не было fastforward. по той ссылке, с которой вы взяли картинку, чувак с ником "Apreche" делать merge-коммиты. Например показывает, что merge легче откатить, так как это один коммит, а не все мелкие коммиты.
Если делать fast-forward, то чем это всё отличается (глобально) от например svn?

А картинка должна была проиллюстрировать то чем эти мерж коммиты плохи.
выражение "merge-коммиты плохи", у меня ассоциируется с "ветвления плохи".
merge'ить ветки естественно , а полностью вливать одну ветку в другую - нет.
вот почитайте, что авторитет пишет http://kerneltrap.org/Linux/Git_Management .
например про rebase: "and basically use git as an efficient
patch-queue manager that remembers *your* patches"

Покажите свою, давайте лучше ее обсудим.
Я гит использую как клиент к удалённому svn'у - там всё линейно.
Локально же у меня feature-бранчи, которые вливаются в master, через merge --no-ff, всё чисто и аккуратно.
Мои картинки скучны - слишком прямолинейны, а обсуждать чужие похоже не очень интересно.
Неинтересно обсуждать чужие, тогда когда не ясно как эти картинки получились, и что вообще там творилось - если дадите ссылку на какой-нибудь реальный репозиторий, то я с радостью обсужу его картинки .

Почитал я письмецо в кернел трап.
Думаю самое время подвести итог. Похоже кто то всетаки находит пользу в мерж коммитах, они им нравятся и все такое. Я пожалуй спорить не буду (да я особо и не спорил). У каждого свои проекты, люди. Если почитать Линуса, то вообщем то ясно, что он не может ребейзить физически из за того, что у него тоже вытягивают какие то ветки. К томуже 2500 патчей звучит как то уж совсем дофига, я так понимаю что это даже не коммиты. У нас пулят только из одного места, в него все и сливают. Есть проект в котором сливают в мастер и если тесты зеленые то скрипт это все дело _мержит_ в мастер-стейбл. То есть ребейзить можно,
что мы и делаем. Такой воркфлоу у нас уже 2,5 года и проблем с историей небыло. Кол-во коммитов можно глянуть тут:
https://qt.gitorious.org/qt-components/qt-components
и тут
https://meego.gitorious.org/meegotouch/libmeegotouch

Все же кернел это не рядовой проект. Да и Линус с камрадами я скажу не рядовые личности. Я нисколько не сомневаюсь что они смогут разобраться кучей мержовых коммитов. Другое дело что у нас в комманде таких людей нет :)

* например про rebase: "and basically use git as an efficient patch-queue manager that remembers *your* patches" *
Это как раз то, что я хотел написать, что гит эффективный менеджер патчей. Только получается, из его слов что ребейзят лузеры а уж на полную катушку гит используют чуваки которые мержат. Но рано или поздно станет ясно что лучше для конкретного проекта.

Про статью с хабра...Вообщем, к чему то подобному мы тоже пришли. Есть бранчи для релизов (1.0, 2.0) в которые черипикаются баг фиксы, есть таги, только ветка стабильная одна - мастер. если она не стабильная коммит сразу откатывается. Практика показывает что если что то может быть нестабильным оно будет нестабильным всегда. Вся работа ведется в клонах, а патчи засылаются merge requestами. Есть несколько человек которые их пушат. Когда пушили все, билды были красными.

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

В целом ваша позиция ясна, я надеюсь моя тоже (а на большее я и не расчитывал :) )

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

я вот этой ситуации не понял. но если это про rebase в общем репозитории, то это как бы bad idea. про это даже в http://kernel.org/pub/software/scm/git/docs/git-rebase.html написано:
"Rebasing (or any other form of rewriting) a branch that others have based work on is a bad idea: anyone downstream of it is forced to manually fix their history. "

Это, как справедливо написано в мануале, bad idea в тому случае если ребэйз делается с коммитами которые уже лежат на сервере. Для локальных коммитов таких проблем нет. Уже два года ребейзим всем маемо, и никаких проблем.

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

Usually you cannot revert a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows revert to reverse the change relative to the specified parent.

Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want.

Это, как справедливо написано в мануале, bad idea в тому случае если ребэйз делается с коммитами которые уже лежат на сервере. Для локальных коммитов таких проблем нет. Уже два года ребейзим всем маемо, и никаких проблем.
читаем заново моё высказывание "я вот этой ситуации не понял. но если это про rebase в общем репозитории, то это как бы bad idea."
я не говорил, что rebase в локальном repo это bad idea.

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

Ну в описанной ситуации с Линусом, там всё ясно. Если revert - это всего лишь reverse commit, то так и должно быть.
А вот чтобы было в той ситуции, если бы делали rebase? Точнее что по вашему было бы в варианте с rebase?

* А вот чтобы было в той ситуции, если бы делали rebase? Точнее что по вашему было бы в варианте с rebase? *

Если я правильно понял вопрос, то с rebase история получается линейная, и как следствие revert работает правильно потому как можно откатить любой патч, а потом откатить откат и все такое.

Ну так в случае с merge, в обсуждении с Линусом, именно советуется откатить откат, то есть тоже самое.

http://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-me...
"In such a situation, you would want to first revert the previous revert"

Сюда тоже СПАСИБО!!!
Я это тоже все перечитал. На этих графиках крыша ехала.
Теперь (после всей последовавшей дискуссии) стал въезжать для чего это надо.

Ну вот я в мастере говорю git merge vendor-branch и импортируются только те изменения, которые были с прошлого merge.

Ну правильно, вы ведь ветку vendor-branch не удаляете - а кладёте следующую версию dcraw.c в ту же vendor-branch.
Когда вы вливаете одну ветку в другую, даже с удалением вливаемой(это не касается вашего примера) - коммиты ведь остаются из обоих веток. А вот история о том, что вот этот коммит когда-то принадлежал ветке feature - нет. И вообще, после того как master пойдет дальше слияния, различить какая из веток коммитов была master - нельзя.

И после этого ветка feature нафиг не нужна.
я знаю что-такое topic/feature-branch, сам недавно начал их использовать.
Я не говорю, чтобы после удаления ветки, она была видна в git branch. Пусть будет видна в через специальную архивную команду.
Вот мне через год будет интересно, как именно я игрался с ветками - это же VCS.

Вот сделал копию одного репозитория, грохнул master (предварительно создав ветку, на самом первом коммите) - размер не изменился..
игрался с git gc - размер не изменился.. погуглил - нашёл
http://www.kernel.org/pub/software/scm/git/docs/git-reflog.html
То есть вроде инфа всё-таки хранится, что уже хорошо.
Вот только перепробовал уже кучу команд - а грохнуть размер не получается :)

Во, git log -g
то чего мне не хватало - значит парой минусов меньше