Как стать автором
Обновить

Комментарии 51

А Github или Bitbucket в качестве сервера почему не захотели использовать?
Потому что в будущем планируем постепенно все проекты переводить на git, а у нас их порядка сотни. Плюс у каждого еще свои svn:externals, которые тоже превращаются в отдельные репы. При таком количестве репозиториев стоимость размещения на стороне растет экспоненциально. К тому же локальный сервер для разработки все равно есть, зачем ему простаивать.
почему не рассматривали mercurial?
Рассматривали, но каких-то значительных преимуществ против git для нас не нашли. А поскольку большая часть разработчиков так или иначе уже имела дело с гитом раньше, то выбор стал очевиден.
Стоимость размещения на bitbucket зависит от размера команды, кол-во репозиториев и место неограничено. Просто для информации, ваш выбор не критикую.
А разве tmp не очищается при перезагрузке? В любом случае, как-то неправильно в tmp хранить то, что постоянно нужно.
Для таких данных есть каталог /var
В том-то и дело, что этот ключ по тому пути больше не нужен. При запуске gitolite setup он этот ключ перекладывает себе в keydir/. Поэтому сразу после setup этот файл вообще можно удалить.
А зачем тогда «сохранить публичный ключ в общедоступном месте»?
Имелось ввиду временно сохранить по короткому пути, чтоб потом набирать меньше букв и чтобы gitolite смог его прочитать.
Вы же gitolite запускаете от того же пользователя, от которого создаете файл. Это в большинстве случаев гарантирует, что он сможет прочитать этот файл.

Между фразами «в общедоступном месте» и «чтобы gitolite смог его прочитать» есть большая разница. Лучше в статье поправьте, а то получается совсем не тот смысл, который вы имели в виду.
А что насчет AD в gitolite?
Только ключи, если использовать gitolite второй версии. В третьей версии система модульная, можно взглянуть на документ sitaramc.github.com/gitolite/http.html. Просто стандартный метод аутентикации — ssh. При использовании smart http она перекладывается на веб-сервер, который может взаимодействовать с чем угодно для аутентикации пользователей.

Резюмируя, gitolite не занимается аутентикацией, но только авторизаций: sitaramc.github.com/gitolite/auth.html.
Ставим gitolite 3.03 на сервер:
$ emerge gitolite


Понт засчитан!

А вообще огромное спасибо за статью! В свое время долго промучился с настройкой gitosis (под тем-же дистрибутивом), а точнее с интеграцией его с redmine.
Этой статьей вы мне не только открыли глаза на мою проблему с устаревшим gitosis, но и дали простое решение.

Если не секрет, какой багтрекер интегрировали с gitolite и насколько это трудно?
Не автор статьи, но отвечу.

Мы интегрировали redmine. Начиная с версии 0.9 и до текущей 1.4 все работает прекрасно. Из особенностей:
  • репозитории должны располагаться на одном сервере с redmine (либо можно клонировать на него специальных хуком при пуше)
  • у сервера, который будет запускать redmine должны быть права на доступ к директории с репозиториями
  • для удобства желательно добавить в репозитории хук, который будет сообщать redmine об изменениях (иначе redmine прийдется постоянно обращаться к репозиториям)


В качестве сервера для запуска использовали fastcgi-обертку в lighttpd и redmine/public/dispatch.fcgi.

Если будет интересно и на хабре это не описано, могу написать статью об этом.
Используем Redmine. Он с коробки поддерживает Git, репозиторий подключался по инструкции: www.redmine.org/projects/redmine/wiki/RedmineRepositories#Setting-up-a-mirror-repository-shortcut-tracking-branches

Обновление локальной копии и подтягивание в redmine производится по крону с некоторой периодичностью, пока этого хватает.
Можно использовать post-recieve/post-update хук такого вида:

#!/bin/bash

REDMINE_KEY=
REDMINE_SERVER=

curl http://${REDMINE_SERVER}/sys/fetch_changesets?key=${REDMINE_KEY}


Для этого, естественно, необходимо сгенерировать ключ и разрешить работу веб-сервиса управления хранилищами в настройках redmine.
Кстати, рекомендую заодно с gitolite посмотреть gitlabhq.
Хотелось бы добавить, что для сохранения директорий обычно в листовых создают .gitkeep, а не .gitignore, последний обычно используется по прямому назначению.

Также стоит упомянуть, что gitolite 3 ещё относительно сырой, Sitaram Chamarty его недавно выложил в публичный доступ. С другой стороны, поломать что-либо там довольно сложно, т. к. вся конфигурация и сами репозитории хранятся, как нормальные bare-repo.
Популяризации такого использования .gitignore способствует github:

Sometimes an empty .gitignore file is used as a placeholder for an empty path, for example to force git to generate a log/ path for your development environment to use.
©github:help
Использование .gitkeep, как и .gitignore с этой целью — конвенции. Лично я предпочитаю использовать .gitignore по его прямому предназначению.

На эту тему можно глянуть stackoverflow.com/questions/7229885/gitignore-vs-gitkeep
Скажите, пожалуйста, какие преимущества может дать Git в плане merge'a функционала в основную ветку? Ведь как в SVN нужно разгребать конфликты после каждого merge'a (если они есть), зато эти конфликты видны сразу; так и в Git при push'e могут возникнуть конфликты, только в этом случае вы заливаете не маленькое изменение (как в SVN), а целую фичу. И не факт, что после этого push'a и исправления конфликтов предыдущая функциональность не разъедется…
После ручного мержа — тоже не факт. Тестирование никто не отменял.
Я и не спорю, просто вопрос возник после прочтения первого абзаца. Вот и хочу узнать, чем так хорош Git в плане merge'a кучи фич в одну ветку.
Ключевая разница в том, что в SVN, чтобы проверить работоспособность фичи в ветке в последних актуальных условиях (голова транка), нужно либо замержить ветку в транк, что в нашем случае не вариант, либо замержить транк в ветку, проверить работоспособность, после чего слияние с транком будет _очень_ болезненным, потому что теперь все изменения транка с момента создания ветки будут самостоятельными изменениями ветки, и в момент слияния ветки фичи с транком мы получим целую кучу конфликтов, потому что одни и те же файлы в тех же местах одновременно менялись и в ветке, и в транке.
Согласен, ветка на фичу — не выход из ситуации. Но чем плохо merge'ить в trunk всем разработчикам в процессе выполнения фич?
Объясню на примере. Например, программисту в процессе выполнения задачи нужна верстка какого-то блока. Чтобы передать работу верстальщику, ему нужно закоммитить частично рабочий код (ведь задача не закончена) в транк, чтобы его увидел верстальщик и мог что-то сделать. Внимание! С этого момента в транке находится частично работающий код.
Верстальщик может быть сейчас занят другой задачей либо выполнение необходимых правок требует значительного времени (дни). Теперь представим ситуацию, что другой программист в это время закончил выполнение задачи, его работа проверена и должна быть вылита на продакшн. Прямо сейчас. Либо же на продакшене был обнаружен критический баг, который требует немедленного исправления. А транк поломан, деплоить нельзя. Что делать?
1) Как на вашем примере поможет Git? Программист зальет частично работающий код… куда? В копию репозитория верстальщика? Это возможно?
2) Что делать? Заливать в trunk закомментаренный код. Верстальщик его раскомментарит, поработает. Когда закончит, зальет в trunk. Гемор, согласен. Возможно, ваш ответ на первый пункт прояснит ситуацию, как сделать без этого гемора.
1. Программист коммитит в свою ветку, пушит на сервер, верстальщик подключает себе эту ветку, сливает в локальную копию, и теперь они вместе работают в ветке фичи, попеременно коммитят и пушат в эту ветку, не затрагивая транк. Задача может выполняться неделями, ведь они никому не мешают, и одновременно взаимодействуют друг с другом, при этом нет никаких ожиданий и простоев.

2. Программист внес изменения в 10 файлов, закоммитил в транк, чтобы у верстальщика работал тот функционал, для которого нужно сделать верстку. Добавим сюда, что программист не один, например их десять. Часть взаимодействует друг с другом, часть с верстальщиками. И все они закоммитили частично нерабочий код, чтобы напарник мог сделать свою часть. Теперь нужно срочно исправить баг. Начинать в логе судорожно искать коммиты, которые они сделали, проходить по кругу и делать опрос, у кого что работает, а что нет, поверить на слово не проверив, отменить изменения в сотнях файлов, при этом не ошибившись ни в одной строчке, чтобы внести на продакшн небольшое исправление, чтобы потом снова вернуть все назад? Это очень удобно)
Уже ясней. Тогда такой вопрос: отдельная ветка в SVN не решает проблему первого пункта аналогично Git?
Решает ровно до тех пор, пока эту ветку не надо будет окончательно тестить и вливать в транк, о чем я уже выше писал. Вот тогда и почувствуется разница между SVN и Git.

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

За то недолгое время, как мы переехали на Git и добили раз и навсегда master до рабочего состояния, у меня еще ни разу не возникало мысли «сейчас нельзя задеплоить на продакшн, потому что...». Потому что причины больше нет. В мастере всегда рабочий код. А работа по разработке новых фич кипит пуще прежнего.
У нас эта тема тоже обсуждалась и мы пришли вот к какому затыку.
Представим, что у нас есть рабочий trunk. Начинается разработка двух новых фич параллельно двумя разработчиками Алисой и Бобом.
Допустим Алиса первая закончила свою фичу, заливает ее в trunk, в итоге мы имеем рабочую фичу в trunk'e. Вроде все пока нормально.
И тут приходит очередь заливать свой код Бобу. Мало того, что он мог поменять код, который меняла и Алиса, так еще их изменения могут носить ортогональный характер! То есть либо Бобу надо изменять свою логику, либо менять логику кода Алисы. В итоге получаем, что все те разработчики, которые заливают после Алисы, должны разгребать конфликты от предыдущих разработчиков, так еще и заливают они не один маленький участок кода, а целую фичу! Ну протестирует Боб свой код. Как он может быть уверен, что он не сломает код Алисы, когда зальет в trunk?

Надеюсь, проблему ясно описал. :)
Тут на помощь снова приходят локальные репозитории гита. Разработчик после завершения своей фичи может локально замержить свою ветку в мастер, если в процессе мержа будут проблемы — он сразу об этом узнает. И тут же он проверяет, все ли ок. Если нет — откатывает мерж и правит код, после чего снова мержит. Если код в мастере сильно поменялся за время выполнения задачи — лучше вообще сделать rebase относительно головы мастера, чтобы код гарантированно ничего не сломал после мержа в мастер, но это только если над фичей работает один человек. При этом все эти изменения происходят локально на машине разработчика, он никому не мешает, пока доводит все до ума.
В результате всего этого разработчик в конечном итоге коммитит исправление в свою ветку, которое позволяет безболезненно замержить потом его ветку в мастер. Сам разработчик мержить в удаленный мастер не может, это порезано на уровне прав доступа к центральному репозиторию. Для этого есть техлид или другое доверенное лицо, ответственное за то, что будет вылито на продакшн.
При этом в истории мастера мы видим чистые мержи фичи1, фичи2 и т.д., без коммитов вида «правка фичи2, чтобы она работала с фичей1».
> Тут на помощь снова приходят локальные репозитории гита. Разработчик после завершения своей фичи может локально замержить свою ветку в мастер, если в процессе мержа будут проблемы — он сразу об этом узнает.

В меркуриале я бы наоборот мастер замержил в свою ветку. Потом бы протестировал и профиксил баги в результате мержа. И только потом свою ветку безболезненно замержил в мастер. В Гите делается по другому?
Нет, всё аналогично. Только смысл иметь два мержа подряд вместо одного? Хотя, в этом плане git лучше — он сделает fast-forward и будет всё равно, кто в кого влился.
Если изменения в своей ветке были не большие, то конечно не имеет. Просто если мерж ломает программу, то ее лучше профиксить в своей ветке, чем в мастере. Пусть уж будет лишний коммит в своей ветке (пусть даже не рабочий), но зато в мастере будет только один коммит, причем профиксенный и рабочий.
в SVN, чтобы проверить работоспособность фичи в ветке в последних актуальных условиях (голова транка), нужно либо замержить ветку в транк, что в нашем случае не вариант, либо замержить транк в ветку, проверить работоспособность, после чего слияние с транком будет _очень_ болезненным, потому что теперь все изменения транка с момента создания ветки будут самостоятельными изменениями ветки

В транк, естественно, мержить не надо. Но не вижу причин не синхронизировать функциональную ветку с транком. Это основной совет как раз для безболезненного слияния с транком.
потому что теперь все изменения транка с момента создания ветки будут самостоятельными изменениями ветки, и в момент слияния ветки фичи с транком мы получим целую кучу конфликтов
Правильно я понимаю, что SVN просто «не помнит» о том, что он влил транк в ветку, в отличие от Git? Отсюда все дальнейшие проблемы?
Я думаю тут проблема в совокупности факторов. Во-первых, svn действительно не в курсе, что куда вливалось, для него это просто коммит каких-то изменений. Хотя в последних версиях он в комментариях обозначает, до какой ревизии было влито, но видимо это его не спасает. Плюс разница еще и в способах организации данных хранилища и способах мержа.
Использую «svnmerge.py merge -bs» для мержа в SVN между транком и веткой. Работает замечательно в обе стороны. Что я делаю не так?

www.orcaware.com/svn/wiki/Svnmerge.py
А вот если разработка в SVN продолжается? Грубо говоря форкается SVN проект под GIT. Форкнуть-то не проблема, но вот вот потом подтасиквать изменения из апстрима как? Вернее даже они подтаскиваются (в консоли что-то идёт), но вот заливать на пшерги нечего почему-то. Никак врубиться не могу. С Mercurial подобная схема работает на ура, а вот с гитом видимо какой-то нюанс не уяснил.
Пока апстрим свн-а не отключен, можно все изменения из него подтягивать через git svn rebase, при этом появляются все недостающие коммиты. Правда для этого нужно было делать git svn clone без опции --no-metadata, потому что git svn ищет последнюю подтянутую ревизию в комментариях истории коммитов.
Спасибо, попробую. Опцию не использовал.
Нашёл другой способ. После начального git svn clone, делаю git svn fetch , при этом внезапно (для меня) изменения стягиваются в ветку git-svn, с которой уже работаю как с обычной веткой в частности git merge git-svn.

Столкнулся правда с тем, что если реп залить на гитхаб, то настройки giit-svn не сохраняются, нужно в клонах гитхабовского репа их ручками вписывать, но при этом всё довольно прозрачно работает.
Уже в двух фирмах проводил ту же операцию, использовал:
1) GitLab для визуализации реп
2) авторизация по логину/паролю от GitLab, а не ключу
3) во 2ой конторе GitLab ставился рядом с уже работающим gitolite
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Нашел на сайтике способ, как сгенерировать список пользователей
svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации