Pull to refresh

Comments 147

Спасибо, полезная статья. С неё можно начать использовать Git и потихоньку уходить от SVN :-)
Хотя в своём интервью Линус Торвальдс говорил, что SVN продолжает отлично работать в большинстве проектов, но Git хорош в больших и сильно распределённых проектах.

Так что надо пробовать, и самому делать выводы.
Я вроде смотрел интервью с Торвальдсом и его выступление по поводу git в Google.

Svn выглядит довольно неуклюже даже в маленьких проектах. Его папочки раскиданы по всему дереву проекта, репозитарий создается сравнительно долго, хранится отдельно…

А в git создание репозитария в проекте выглядит так:

cd project
git init
git commit -a -m «initial commit»

Easy pie, не находите?
Зато в SVN есть атомарная история каждой мелочи, чем я активно пользуюсь. В Git её нет.
Не совсем, там есть целый комплект специальных команд для исследования истории изменений. Надо будет как-нибудь специально сравнить.
создание репозитария — разовая операция. время не критично
В SVN при commit нужно прибавить время пересылки данных. Сделать несколько коммитов в свой репозитарий и отослать всю пачку быстрее.
Да и в SVN существенно медленее выполняются и сами операции.
Ну все это спорно.

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

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

Если репозитарий в локальной сетке, то commit выполняется относительно быстро. Update — дольше. Но лично для меня время коммита/апдейта не настолько критично чтобы менять СКВ.

Вот если разработчики разбросаны по миру, то тут наверное git будет удобнее. Да. Возможно удобнее делать патчи.

Скажите, если вы с git работали — там конвертатор есть какой-нибудь. svn -> git, cvs -> git и обратный?
svn -> git — есть стандартный, с полным сохранением истории.
cvs -> git — напрямую нет, советуют сделать cvs -> svn -> git :)
Вставлю свои пять копеек: в SVN самая «убойная» команда — svn log, особенно при работе с удаленным репозитарием. git log выполняется мгновенно.
ну он же на то и лог. а как часто вы выполняете эту команду? при каждом коммите? при каждом втором? при каждом двадцатом? раз в день? раз в неделю?
при каждом. что бы посмотреть что в общественный реп не уйдейт что-то ненужное.
не совсем понял насчет «ненужного»

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

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

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

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

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

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

Чаще всего есть две-три ветки. Одна из них это master и HEAD в ней — последний коммит, извлеченный с центрального репозитария. Плюс одна веточка на новую фишка. Заканчиваешь работу с ней — сливаешь в основную. Коммиты в результате становятся мельче и точнее. Можно, к примеру, вытаскивать отдельные подкоммиты в дочерней ветке и вливать в master.

Не надо путать ветки в svn и ветки в git. В первом ветка — это тяжелое изменение, накапливающее множество изменений. Естественно, что ее трудно слить в главную. В git ветка, это скорее веточка, включающая буквально два, три, редко пять коммитов.

Обычно в центральном репозитарии вообще хранится одна ветка, а ля subversion, которая и будет на выходе проекта. Тут действительно не стоит разводить сложных деревье; более того, сознательно поддерживается простая линейная история разработки.
«Плюс одна веточка на новую фишка» — насколько я понял преимущество git тут в том, что в конечный бранч мы можем надергать этих веточек (не все использовать) и оно автоматом вольется без необходимости мерджа? Крайне мало времени в проекте занимают такие изменения, если продукт уже относительно зрелый, то изменения — это слоеный пирог, вытащить нижний слой без проблем не получится (!)

«Не надо путать ветки в svn и ветки в git» — никто же не запрещает делать ветки в svn такими же короткими как в git, пусть у вас хоть на каждую фичу будет своя ветка, а потом сливайте нужные ветки (фичи) в один бран, если они действительно независимы, то мерджа не будет.
Учите, что все это колдовство в svn будет в главном репозитарии, что только запудрит голову всем разработчикам. В распределенных системах git push в главное хранилище делается уже после разборок со всеми проблемами на месте.

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

Что такое «главный репозитарий» я не очень понимаю, с точки зрения svn репозитариев может быть несколько, а в каждом репозитарии ветвиться можно по каталогам.
Я работал года два с Svn, и в обоих более или менее приличных проектах тимлиды по возможности избегали ветвления. Насколько знаю по знакомым, такая схема считается нежелательной. Кажется, вы можете больше моего рассказать о причинах этого!

Опять же, ни разу не встречал схемы с несколькими репозитариями.
вот-вот, а в ClearCase так вообще без private branch не работают.
Мне тут еще в голову пришло…

Что-то не помню, чтобы наш тимлид вообще кому-либо позволял разводить такой бордель в центральном репозитарии :) Это ж форменное безобразие!
Не повезло вам с тимлидом.
В git ветка вообще может быть только в вашем локальном репозитарии, поэтому советуют делать ветки прямо постоянно на каждую добавляему фичу — в глобальном репозитрии (тот который для синхронизаии) лежат только общие ветки. Так что ветки в любом случае в Git создвать проще.
Создание ветки в SVN делается за время O(1) и место O(1).
Как говорил Линус в Гугле, фишка не в том, как быстро и просто ветка создается, а как быстро и просто ветки потом сливаются :)
Это было возражение по поводу «Так что ветки в любом случае в Git создвать проще».
Ну, а я лишь бесцеремонно влез в чужую беседу и намекнул, что созданием веток работа с ветками не ограничевается ;)
Я говорил про орг. вопросы. Т. е. когда все ветки глобальные, то ради одной фишки ветку делать не будешь. А в git у тебя могут быть чисто свои ветки, которые никто не увидят.
Какая разница глобальные или нет? Вы при работе с SVN постоянно лазите в /branches и смотрите какие ветки кто добавил?
Ну хотя бы имена без конфликтов нужно выбирать.
Это вопрос договоренностей. И потом врядли кто-то будет создавать ветки в /branches/your_username/…
центральный свн будет полон того что там могло бы и не находится. учитывая что свн копирует файлы для создании ветки/тэга. удаленная работа с репозиторием будет неудобной и мучительной. тем более что многие просто побоятся/поленятся что-то коммитить в общий репозиторий т.к. этот код еще сырой. в результате каждый коммит это уже почти полноценная фича которая заливается в общий свн репозиторий и о легковесности слияния не может быть и речи. да и о работе оффлайн тоже.
центральный свн будет полон того что там могло бы и не находится
И кому это мешает? К тому же ветки после слияния в транк можно удалять, чтобы глаза не мозолили.

учитывая что свн копирует файлы для создании ветки/тэга
Не копирует.

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

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

Вот работа оффлайн — это пожалуй единственный весомый аргумент, из приведенных вами.
не знаю как вам, а мне еще весьма приятно что базовые операции выполняются очень быстро. да, те самые мержи, о которых тут много было сказано. еще мне приятно то что мы с напарником можем обмениваться кодом вообще не затрагивая центральный репозиторий. ну и вдобавок к вышесказанному нравится даже то, что я могу работать с svn сервером используя git.
Не спешите уходить с централизованных репозиториев.
давайте тогда уж на цитату Линуса, где он говорил что-то хорошее про SVN. все выступление он только и говорил: «ребята svn — говно, вот, смотрите как это можно было сделать лучше». и так далее. упоминание того, что SVN используется успешно в мелких проектах не значит что git не может использоваться как минимум с той же степенью эффективности.
Спасибо. Давно хочу попробовать какую-нибудь распределенную систему контроля версий, правда еще не решил какую, вот разрываюсь между git и mercurial.
Mercurial. Кросплатформенна (git вроде собирается только под линух). Есть плагины для всех IDE, отдельные гуи. Вообще реально для небольших корпоративных проектов я не видел причины почему не справится обчный svn.
Эти времена в прошлом; теперь git не только подо всеми юниксами, но и под виндой есть.

А вообще пахнет религиозностью :)
> git вроде собирается только под линух

Судя по всему не только. Есть даже TortioseGit.

> Есть плагины для всех IDE

Меня устраивает Tortoise*, а она есть и для Mercurial, и для Git.

> Вообще реально для небольших корпоративных проектов я не видел причины почему не справится обчный svn.

Пока хочу просто попробовать. Правда, возможность избавиться от назойливах папок .svn тоже привлекает :)
Вы не избавитесь от них, а только получите папки .git ;)
Папку .git в корне, а не .svn в каждой папке проекта.
TortoiseGit вроде сыроват ещё. В последний раз когда я его пробовал была куча заглушек-диалогов.
Жаль, конечно. Но все-равно для начала надо поюзать обычную консольную версию.
В том-то и дело, что для небольших проектов лень заводить сервер и т. д. Так что для личных/небольших проектов git даже удобнее. Кроме того, в git изначально другая идеалогия работы с ветками.
дело вкуса что использовать для проекта. у кого-то большая эффективность с svn у кого-то c git. =)
p.s. git есть уже и под win и под mac os x. и GUI есть тоже кросплатформенный. (qgit например)
В защиту Git (но с большим уважением к mercurial) скажу, что считается, что в Git проще со слияниями веток.
И концептуальное преимущество git — очень простая его структура — в неё всегда можно залезть руками. См. los-t.livejournal.com/tag/git+guts
Спасиб. На досуге почитаю :)
Кстати, а при таком большом количестве веток по идее и конфликтов должно возникать больше. Или нет?
Насколько я понимаю, одна из идей состоит в том, что чем больше веток/коммитов, тем меньшие части кода в них изменяются, а значит собирать всё воедино проще.
А как же тогда быть с примером, когда находишься далеко от репозитория и пишешь, пишешь и пишешь. Собственно, это меня больше всего и привлекает в этих системах.
Да, именно из-за подобной ситуации я и стал использовать git.

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

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

* Для каждой фичи делаем ветку, но по ее завершению в свой master не коммитим
* Когда получаем доступ к телу главному репозиторию, обновляем свой master
* В свой master коммитим все изменения главного мастера и заодно правим конфликты.
* Коммитим свой master в master главного репозитория.
Именно. В мастере главного по-прежнему остается красивая прямая линия разработки, особенно если ее аккуратно размечать тегами.

Есть еще такая команда git rebase, которая позволяет поддерживать линейность главной ветки центрального репозитария. Я о ней не писал специально, чтобы не пудрить мозги лишней информацией.

Строго говоря, ничего страшного в git rebase нет, это просто такой способ «бесшовного» объединения вашу и других разработчиков работу, когда изменения проводились параллельно.
можно и по другому, если фича одна, но объемная.
* Делаем ветку, в ней работаем и делаем мелкие коммиты — не длинее дня.
* Регулярно обновляем свой мастер с главного репозитария
* Делаем слияние с обновленного мастера — в ветку с фичей, то есть подтягиваем общий код фичи до текущего состояния.
* Когда решили что фичу надо зарелизить — делаем обратное слияние в мастер и главный репозитарий.

При таком подходе — конфликтов на релизе почти не бывает =)

ЗЫ. А можно ветку и не релизить в мастер — по этому принципу форки опенсоурсных проектов работают.
А ещё, по мере поступления обновлений в master, их можно элементарно сливать в остальные локальные ветки, чтобы в них тоже попадали все последние багфиксы.
Причем делать это можно как через git merge, так и через git rebase.
Последний — это вообще шикарная фича, но пользоваться её надо с умом и осторожно.
благодаря вашему комменту, я понял, в чем преимущество git, спасибо.
Мой опят работы с VCS не очень большой, но логика подсказывает, что смержить очередной коммит в SVN может быть для системы более сложной задачей, чем последовательно применить десяток более мелких в Git. Тут уж ничего не поделаешь, у нас с вами разная логика :) В конечном счёте аккуратность решает, просто не нужно накладывать заплатки на одно и тоже место, а в крайнем случае переписать заново функцию/блок.
В общем, надо попробовать на своей шкуре :)
Смотрите выше. Заметка именно про особенности workflow.

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

Мой опыт показывает, что конфликты возникает примерно с той же регулярности, что в Svn, ничего особенного.
git branch new-feature
И переключимся на нее (обратите внимание на отличие в терминологии по сравнению с SVN):
git checkout new-feature

Аналогичное проще: git checkout -b new-feature
А где самое главное — как решать конфликты ?? :-)
Да, ещё — как например откатить до какой-то версии, с помощью тегов?
В общем, видимо надо ещё одну статью, а то по git не было ничего, а лично мне интересно очень, ибо svn слегка напрягает.
Ну… Я поищу по Хабру, и если действительно ничего похожего нет, то через неделю наклепаю статью уже не столько по общему workflow, а именно деталям работы с Git.
Спасибо, обязательно почитаем!
UFO just landed and posted this here
вот отличные туторы для новичков, мне в свое время очень помогли. возможно пригодятся как основа для статей
www-cs-students.stanford.edu/~blynn/gitmagic/index.html
kdiff3, WinMerge и тому подобное, может быть? при чем тут системы контроля версий?
Мммм… Я про то, каким образом специфично для git такие ситуации разруливаются. Просто не юзал его, прочитал эту статью, выглядит проще чем svn, а вот как он с конфликтами работает — может какие специальные команды есть, и т.д. В этом смысле.

В Windows да, WinMerge, в Ubuntu юзаю Meld (по-моему, стандарт). По крайней мере, он настолько удобнее всего остального, что меня устраивает на 110%.
Я порылся по Хабру и никаких подходящих статей не нашел. Видимо, быть заметке обо всяких деталях.

Но если в двух словах…

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

Выглядит это так:

git merge conflicting-branch
>>>>> здесь тебя оповещают о конфликтах
edit TROUBLED_FILE
git add TROUBLED_FILE
git commit -m «resolved a conflict»

Ну вот и все, конфликт решен, никаких новых комманд.

Выглядит здорово, спасибо!

Остаётся вопрос об откатах или переключениях на другие версии :-)

Вообще, конечно, было бы отлично видеть это всё в виде статьи — эту я в избранное добавил, вот вторую туда же бы — и вуаля, миниучебник по гит в кармане :-) Мечта!
Да, я хорошо читаю по-английски и знаю, что есть howto и доки по git. Но мне понравился стиль изложения именно _этого _ автора — всё чётко, ясно и понятно :-)
Откат к какой-то версии в репозитарии:
git reset ВЕРСИЯ --hard
Откат к предпоследней версии в репозитарии:
get reset HEAD^ --hard
Можно писать HEAD^^ и т. д., можно указать примерное время коммита, а можно просто SHA1-номер версии (или первые несколько его букв, чтобы они были уникальны).

Команды выше применяют изменения только на репозитарий, файлы в рабочей папке изменяются отдельными командами:
git reset ВЕРСИЯ
и т. д.
Например, если вы программировали-программировали и поняли что фигня получается, то откатить все изменения в рабочей папке:
git reset HEAD
Чтобы просто подправить сообщение последнего коммита (орф. ошибка и т. д.):
git commit --amend
А если нужно не последнего?
Сложнее и с помощью отдельного коммита. Но подробностей не изнаю ибо не использовал. см. git.or.cz/gitwiki/GitTips
Обычно нужно бывает подправить коммит, находящийся не очень глубоко в истории. Поэтому мне вполне хватает git rebase --interactive.
практический безболезненный мердж в DVCS существует просто в силу их организации.
репозиторий svn представляет собой, по сути дела, набор снимков состояний дерева каталогов. и ветки там — просто каталоги, а мердж — наложение снимков состояний одного каталога на другой каталог. хранением истории слияний приходится заниматься или в уме (до svn 1.5) или в метаданных (после), иначе возможно повторное применение изменений, чем собственно и неприятны слияния в svn.
в DVCS репозиторий — ациклический направленный граф (DAG) состояний одного и того же каталога, поэтому при мердже приходится объединять два состояния каталога в одно (в hg это максимум, в git у ревизии может быть множество родителей), что может быть проведено автоматически, а конфликты разрешаются вручную с помощью внешних утилит. потом осуществляется коммит и мы вместо двух веток получаем одну. в результате история слияний гораздо нагляднее.
Т.е. историю слияний можно посмотреть графически, в виде дерева, средствами самого git, или для этого надо сторонний инструмент использовать, такой есть?
В принципе, есть отдельная утилита gitk, я иногда использую именно ее.

Не так давно вычитал про новый ключ команды git log, он выведет ASCII-репрезентацию истории коммитов. Лично, однако, не видел — у меня до сих пор живет Ubuntu 8.04, обновляться же пока на работе и дома использую один ноутбук слишком рисково. Но скриншоты выглядят довольно мило :)

Вызывать так:

git log --graph
Для GNOME довольно красив giggle.
Так же, с помощью GUI или вручную (закоммитить файлы с метками merge нельзя). Но при постоянных, но небольших (как следствие) ветках вероятность конфликта существенно снижается.
Хочу предложить ещё один неплохой репозиторий unfuddle.com (1 проект, неограничено репо, но 2 человека — бесплатно).

И в качестве комментария, хочу отметить, что Git на моей машине с удалённым репозиторием unfuddle связывается и делает push/pull быстрее (в несколько раз!) чем svn с сервером, находящимся в соседней комнате. Масштабы проектов примерно одинаковы.

А говорят, что Mercurial ещё быстрее :)
Mercurial не так сильно быстрее: сравнение. Они больше по идеалогии различаются.
Я ж и писал «говорят» :)
Меня скорость Git-а устраивает, а как известно, от добра добра не ищут :)
если слияние будет проходить быстрее чем сейчас, не 1,5 секунды, а 0,9 секунды. Я прям не знаю, куда я буду использовать эти освободившиеся за день 10*0,6=6 секунд… :)))))
> Они больше по идеалогии различаются.

А можно поподробнее в чем именно
git для гиков — крутая кривая обучения, нужно сначала понимать внутренности системы, чтобы эффективно работать.
mercurial для негиков — консольные команды похожи на svn, основная функциональность постигается за два часа, более продвинутые возможности — за счет расширений (bookmarks, convert, rebase, shelve и тд)
да ну, не могу согласиться.

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

Это все больше очередная айтишная легенда, вроде стиля такого.
В защиту Git: он действительно для гиков, поэтому он «просто, но нужно быть гением, чтобы понять его простоту». И кроме того, он более соответствует духу UNIX. См. los-t.livejournal.com/tag/git+guts
Такой вопрос — можно ли в git (и вообще распределённых системах) делать таск-бранч доступным разным разработчикам, а не только себе локально?
Поясню. У меня в проекте в svn используется следующая практика.
Есть основной репозиторий (транк). При необходимости сделать какие-то изменения, девелопер открывает таск-бранч (копирует транк через svn copy). После делает изменения в таск-бранче и коммитит туда. Соответственно потом тимлид может взять этот бранч из общего репозитория, проверить изменения и смержить в общий транк. То есть это практика проверки девелоперского кода и безопасности основного репозитория от случайных коммитах.

Есть ли какая-нибудь аналогичная схема для git/mercurial/etc.?
Конечно, такая возможность есть.
При использовании отдельного репозитория в качестве центрального, любой разработчик может «опубликовать» на нём свой локальный бранч и таким образом организовать совместную работу.
Спасибо, а можно немного конкретики? То есть как именно разработчик может это сделать?
Из статьи видно что создаётся бранч локально, и локально же потом мержится в мастер-репозиторий. А как этот же бранч сделать доступным всем?
можно коммититься в удаленный репозитарий, создавать там ветки и, разумеется, админ может определять политику происходящего.

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

Время терпит? :)
Конечно терпит =) Я тут начинаю с меркуриалом разбираться — принципы тот же как я вижу, а там надо будет что-то такое придумывать. Так что пока интерес гипотетический, но всё равно было полезно знать, спасибо!
Тут очень важно правильно понимать концепцию распределенности.
Локальный бранч и удаленный бранч — это всё же разные бранчи, даже если локальный бранч следит (tracking) за удаленным и они имеют одинаковые имена (хотя имена тут не имеют вообще никакой роли).

Есть одно неплохое руководство по гиту — Git Guide.
На основе его могу привести пару примеров работы с удаленными бранчами.

Итак, вначале создаем локальный бранч с именем foobar и переходим в него:
$ git checkout -b foobar

Дальше можно сразу же опубликовать его, а можно вначале закоммитить в него что-то — смотря как вам удобнее. В любом случае, когда решите публиковать его на сервере по умолчанию (origin), выполняете такую команду:
$ git push origin foobar:refs/heads/foobar

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

$ git checkout --track -b foobar origin/foobar

Я опустил пару полезных моментов, в которые стоило бы углубиться, но в целом этого вполне достаточно для работы с удаленными бранчами.
Спасибо за линк и комменты. Завтра обязательно поставлю гит и попробую что-нибудь такое сделать.
А если вместо
git push origin foobar:refs/heads/foobar
использовать
git push origin foobar:foobar
? Это ведь будет работать, или нет?
Попробуйте :)
Мне сейчас неудобно экспериментировать, под рукой только корпоративный сервер.
Всегда пользовался вторым спосбом, проверил первый — разницы не увидел
Во-первых, в действительно больших проектах можно использовать иерархию репозитариев.

Кроме того, в файле по адресу your-project/.git/info/allowed-users возможно оставлять совсем точные указания по управлению доступом к веткам, созданию тегов и прочему. Пример содержимого файла с первого попавшегося howto:

refs/heads/master alice\|cindy
refs/heads/doc-update bob
refs/tags/v[0-9]* david

Первая строка показывает, что alice и cindy могут коммититься в главную ветку (женщины), bob — в doc-update; а david, как технический менеджер, может заниматься заданием тегов-версий приложения.
Спасибо, но второе мне кажется не совсем то — это распределение ролей кто куда может коммитить. Но если девелопер не может коммитить, скажем, напрямую в master, но должен сделать и выложить патч для неё?

иерархию репозитариев — сорри, что имеется в виду? иерархия по какому признаку?
можно разрешить разработчику создавать ветку, но запретить коммитить в master.

Иерархия — система репозитариев. Например, есть четыре младших девелопера, два старших и архитектор.

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

Ок, теоретически ясно, спасибо. Жду последующих статей =)
В разработке Линукса применяются т.н. «pull requests» — обычные сообщения электронной почты типа «Эй, приятель, забери-ка из моей ветки super-feature те шикарные изменения, которые я в неё внёс!»
Конечно же, эти вещи можно автоматизировать (например, это делает GitHub), но простор для фантазии практически безграничен.
Gentoo:

emerge -av git

* dev-util/git
Latest version available: 1.6.0.6
Latest version installed: [ Not Installed ]
Size of files: 2,725 kB
Homepage: git.or.cz/
Description: GIT — the stupid content tracker, the revision control system heavily used by the Linux kernel team
License: GPL-2

Клёво.

А по факту, я не совсем понял — как можно вернуться к какой-то определенной ревизии? Бывает, что программист либо в коде накосячил сильно либо удалил что-то нужное и необходимо вернуться назад на какое-то количество шагов. Подскажите, как быть?
Редко возникает необходимость откатить именно кучу изменений.
Отдельные коммиты можно откатить командой «git reset».
Имейте в виду, что она не имеет ничего общего с командой «svn reset», кроме названия.
Этой же командой можно отменять целые мерджи, но делать это нужно осторожно, потому что… в общем, тут начинаются сложности.

Можно откатить и все коммиты до определенной версии, но только в том случае, если эти изменения ещё не покинули пределы вашего репозитория — для этого есть команда «git reset». Только с ней нужно быть ещё осторожнее — в умелых руках, она может уничтожать коммиты безвозвратно :)
git reset --hard имя комита (хеш) к которому необходимо вернутся
Эти системы строятся вокруг централизованной модели разработки, в которой существует единственный удаленный репозитарий, в который вносят изменения все разработчики проекта. Ветвление (branching) проекта возможно, но не желательно и приносит, как правило, только дополнительные сложности в проект.


Ветвелние к централизации-децентрализации никакого отношения не имеет. Все дело в удобстве работы с ветками в той или иной системе. В CVS это «ужас-ужас», в subversion немного получше, но проблемы с reflective/cyclic merges мешают жить хорошо. В Perforce же (уж на что централизованая и old school система, без доступа к репозиторию ничего не работает) ветки одно из основных понятий.
В децентрализованной системе есть личные ветки для каждого разработчика. Это позволяет не думать над именами и не засорять ветки центрального репозитария. Поэтому в git принято на каждую фичу делать ветку у себя.
По мнению Forrester — Subversion — лучшая система версионного контроля в категории систем без функционала управления изменениями. В подкупе Gartner сложно заподозрить, тем более что Subversion — бесплатная система. The Forrester Wave™: Software Change And Configuration Management, Q2 2007

По-моему мнению, неправильно сводить выбор технологического инструментария для конфигурационного управления к удобству управления ветками. Есть требования инфраструктурные, есть процессные, есть секьюрные требования и т.д. Например, для CMM 3 необходима интеграция системы конфигурационного управления с системой управления изменениями (issue management, change management). Где-то требуется обязательный доступ через WEB, где-то высокие требования к ограничениям прав доступа к исходникам. А кто-то жить не может без интеграции со средой разработки. Не последнюю роль играют организационные факторы — наличие на рынке труда специалистов, знающих инструмент, а также наличие технической поддержки продукта в России.
Проблема в том, что Git|Mercurial|Bazaar имет все возможности Subversion. И раз она такая крутая, то почему все (Linux, Mozilla, GNOME и т. д.) с неё уходят? ;)
речь идет не только о ветках. Разные бывают подходы к этим вопросам и среди распределенных систем тоже, топик освещал конкретно стиль git. Разговор идет прежде всего о системе репозитариев, а тут гибкости у централизованных систем нет по определению.

Финансисты же — народ консервативный, даже в айтишной сфере; им проще судить о том, что было и сейчас в зените популярности; а том же, что только входит в мэйнстрим, они рассуждать не могут и не будут. Тут надо обращаться к аналитикам другого рода… Прежде всего надо спрашивать у самих разработчиков.

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

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

еще ожидал упоминаний про интеграцию в основные среды разработки. конечно к workflow это не относится, но всё-таки является дополнительным аргументом к использованию git.
nbgit: This module is not stable and may randomly crash, eat all your memory, or otherwise mess up your NetBeans IDE. So consider yourself warned!
Что есть, то есть :) Но раньше было ещё хуже :).
Единественно замечание к бэкапу файлов с помощью git — он не сохраняет права на файлы. Поэтому бэкапить конфигурационный файлы, например, /etc, не стоит.
Хм. Надо проверить.
для этого есть модифицированный git:
eigenclass.org/hiki/gibak-backup-system-introduction

из описания почему пришлось делать gibak:
The major thing missing in Git when used as a backup tool is support for file metadata (mostly file permissions) and empty directories (git just ignores them). git-home-history doesn't handle them at all, and etckeeper relies on metastore to preserve a snapshot of the metadata (owner, group, permissions, mtime, etc.) in a .metastore file located at the top of the git repository (/etc in the case of etckeeper).
Не в курсе, а svn сохраняет?
И время модификации файла :( Но по идеи, это вообще не касается системы контроля версий.
Согласен, что не касается. Но это предостережение для тех кто захочет использовать его в качестве бэкапа. Просто что бы имели ввиду.
Вопрос по workflow: допустим есть основная ветка изменений «чистовая» и есть «рабочая» ветка, которая содержит несколько локальных изменений в проекте, которые не должны быть в чистовом варианте, но которые всегда необходимы для разработки. Т.е. другими словами в «черновом» коде хочется видеть всегда несколько «особых» изменений, сделанных один раз и давно, и не хочется держать их в голове, и в то же время не хочется видеть эти изменения в «чистовой» версии и помнить о них при каждом мержде.

Пока что не нашёл простого способа заставить системы контроля версий (и git в частности) работать в таком стиле, но мне кажется, что подобный стиль очевиден и многие должны с ним столкнуться. Как вы поступаете в таком случае?
конкретного примера хотелось бы. если речь идет о различной конфигурации, то файл конфигурации можно не добавлять в vcs вообще.
Файл конфигурации слишком простой случай, но и тут можно изредка получать головную боль. Не держать его в vcs вообще, не сильно удобно, т.к. в нём всё-таки относится к проекту и необходим во многих случаях именно с дефолтными установками. Можно конечно держать его незакомиченным, но тут получим много неудобств как только в него добавят «чистовые» изменения. В этом случае, пока мы не удалим или не закоммитим свои личные настройки, ни смерджить ни даже переключиться на другой бранч в, котором этот конфиг изменён, git не позволит. Придётся пользоваться нычками (stash) или другим бубном.

Но это конфигурации, в них редко делаются правки. А если это центровой и очень популярный в проекте файл, в который довольно часто льются коммиты и в котором так удобно держать свой код, который, например, дапмит в файл только вам нужные данные?
Пожалуй, есть два способа. Первый — команда git revert. Она создает новый коммит, отменяющий старые изменения.

Например,

git revert BAD_COMMIT_TAG

отменит какое-то из коммитов в истории, который вы пометили как плохой.

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

Другой способ, если изменения не коснулись кого-либо кроме вас — команда git rebase, отвечающая за физические изменения в истории проекта. Пример:

git tag BAD_TAG work~5 — отмечаем проблемный коммит (пять коммитов назад по истории в ветке work) тэгом

git checkout BAD_TAG — переключаемся на этот коммит

… убираем ненужные вещи

git commit --amend — собственно, коммит модификации

git rebase --onto HEAD BAD_TAG work — накладываем последующие коммиты на внесенные изменения
За revert и rebase спасибо. Особенно понравился rebase, надо будет с ним подружиться.

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

Сложный путь — вроде того, что я описал одним моим сообщением выше, когда лезем в историю, физически ее меняем…

Путь, что мне больше по душе — сделать revert слияния:

git revert 81a94bb976dfaaaae42ae2600b7e9e88645ebd81 -m 1

здесь хэш определяет коммит слияния, ключ "-m 1" обозначает номер оставляемой ветки, обычно первый (ветка, в которую вливались).
UFO just landed and posted this here
А почему все учебные примеры использования гита — это «давайте сделаем репозиторий в каталоги и в нем же будем программировать. Это так легко и круто.»? По моему это глупо, в каталоге где активно шуруешь туда сюда, одно неверное движение — и весь репозиторий отправляется в корзину. Даже когда я использую свн только для себя в виде папки — я стараюсь хранить её подальше от /home/%username%
А что вам мешает хранить ваш базовый репоз git подальше от домашних директорий?

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

А для мелких… Для мелких нужна просто возможность контролировать поток небольших изменений и веточек. Вот тут как раз и получается так удобно сделать git init.

Вы все еще скучаете по svn, да? :)
привычка такая привычка!

впрочем уже поднял gitweb, про гитозис читал, но для одиноко стоящего разработчика в поле это имхо перебор.

интересно кстати, совместимы ли гитозис и gitweb?
Я и есть тот самый lonely разработчик. Gitweb не ставил, но gitosis достаточно прост и удобен, местами даже слишком — в ущерб некоторым фичам, нужным иной раз небольшим командам.

Впрочем, есть gitolite или что-то такое.

Короче. Не знаю ничего про gitweb + git(osis) :)
Я использую svn switch, когда нужно быстро переключиться на другую ветку.
Перед этим все изменения должны быть закомичены.
Не вижу пока преимущества Git в этом.
Ветки, конечно, в svn есть. Но каждый раз для переключения вы будете тащить другую ветку с сервера? И все свои локальные эксперименты хотите пихать в главный репоз? Да и незаконченные изменения отложить на время в сторону так легко тоже не получится.

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

Но, признаюсь, жил бы и жил я нормально безо всех этих радостей, если бы не было двух вещей в svn:

1) по проекту разбросан мусор в виде .svn в каждой директории

2) НЕУДОБНО для каждого мелкого личного проекта заводить центральный репоз, потом из него в директорию проекта checkout делать.

А еще в git что очень хорошо, так это удобство настройки файлом .git/config. Переехал с ноутом в другую локальную сеть — достаточно просто сменить адрес условно-центрального репоза — и дальше в работу.

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

Сейчас же даже на работе уже настроил гейт от git к корпоративному svn и пользуюсь в свое удовольствие.
Я сейчас начал изучать Git, потому что drupal.org с сегодняшнего дня переезжает на git (был на cvs и это действительно было неудобно). Хочу понять разницу и преимущества, а не просто спорить.
Отвечу по пунктам.
1) Папки с точкой в начале (.svn) в линуксе — это скрытые папки, хотя я у себя включил показ скрытых папок и они мне не мешают. Когда нужно получить код без этих папок — делаю svn export.
2) Для личных проектов я завожу репоз на assembla.com — пара минут и он готов. По работе мы под каждый тикет создаем ветку и потом мержим в транк (по моему это классическое использование). Тикеты обычно большие, но бывают и на 5 коммитов. Создание бранча в svn дело быстрое, потому как ничего никуда не копируется физически. Мерж тоже 3-4 команды, если нет конфликтов, которые нужно разрулить руками, но это тоже не так и сложно.

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

Пока я так понимаю, что git несколько иначе работает, чем svn. У него есть свои плюсы и свои минусы, которые нужно и полезно знать.
Я, честно говоря, постоянно работаю со скрытыми папками в Линуксе; частенько делаю всякие find -name и прочее, и в целом не люблю, когда в проекте есть лишние файлы. Считайте это моим идеализмом.

В общем, могу сразу обозначить для вас слабые стороны.

1) неприятная работа с большими бинарниками по понятным причинам;

2) пустые директории или файлы в силу архитектуры git невозможны;

3) по первости несколько путает терминология git;

4) роль репозитария несколько уже по сравнению с svn. Если в svn в структуре репозитария запросто можно хранить вообще весь проектный мусор (бинарную документацию pdf или doc, к примеру; исходники сопровождающего проект сайта), то git хотя и позволяет вытаскивать отдельные файлы или директории, но не предназначен для этого. В svn же бранчи — это просто папки, все равно, что хранится.

Из преимуществ.

1) все, что хочется делать с кодом или текстом — в git лучше, быстрее, разнообразнее. Это можно понять и оценить, только поработав; обычно пользователи svn слабо представляют себе разнообразие альтернативных методов работы с хранилищами кода.

2) конечно же, полноценная работа без Инета в силу распределенной природы.

3) вы указали хостинг репозитариев. А вот у меня, к примеру, есть две машины: офисная и домашний ноут. И я запросто делаю синхронизацию кода в любую сторону, без посредников, платных или бесплатных.

Далее мысли в целом по текущему положению дел с системами.

За распределенными репозами образца git — будущее. Это поняли уже все. Даже Фаулер где-то писал про неизбежность постепенного перехода, хотя в первых блог-постах на тему сильно сомневался. Конечно, переход с svn на git, hg, bzк не повысит вашу работоспособность, но определенно упростить жизнь.
Спасибо за подробный ответ. Моя мотивация в изучении git увеличилась и сомненией стало меньше — спасибо ещё раз.
Да не за что. Если будут вопросы — задавайте.
Sign up to leave a comment.

Articles