Pull to refresh

Comments 69

Подскажите, как я понял, у вас для каждой правки отдельная ветка в репозитории? Или для например определенного задания?
Одно задание — одна ветка. Я не различаю задания и правки. Может быть, переформулируете вопрос, я не совсем Вас понял.
Очень хорошая инструкция, только не написали где разработчикам хранить свои ключи.
Применяется стандартный способ авторизации SSH по ключам. Ключи, хранятся в домашних каталогах разработчиков. Я просто не стал вдаваться в детали, чтобы совсем от темы не отходить.
А если задание совсем очень простое — как то поправить пару строчек — тоже делаете под это дело отдельные бранчи?
Я выполняю похожую на вашу роль руководителя, различие только в одном — репозиторий у нас один и работа с ветками устроена немного по другому:
master, как и у вас — стабилен. Туда сливаются только проверенные изменение, которых ждут на production'е. Если что то поменялось в мастере — значит на production'е пора пойти сделать pull.
Разработка же ведется в ветках с названиями dev<номер версии>, например, dev0.8, dev0.11, версии в моем случае — набор задач, который объединяется в версию. Когда цель достигнута — версия тестируется, сливается с мастером и выкладывается на продашкн.
В ситуации, если требуется какая то срочная правка мастера (багфикс) также создается временный бранч, который потом сливается с мастером.
Всякие экспериментальный фичи, которым не нашлось места в версии живет в именнованных бранчах.

Кстати, недавно отошел от трака в пользу redmine. Если вы ведете много проектов плюс очень большой — из коробки поддерживается много проектов, права настраиваются очень гибко. И видно все из одного места, не надо ползать по куче траков.
Тут существенное значение имеет то, на каком этапе разработки находится проект. Если говорить о самых первых этапах, то действительно, бывает сложно четко выделить конкретную задачу. Вроде надо сделать одну простую штуку, а начинаешь делать, оказывается, что сначала надо бы сделать другую штуку, и все это связано с третьей штукой и.т.д. В такой ситуации действительно имеет смысл вести разработку в «крупных» ветках, в которых отдельные правки не выделяются в отдельные бранчи.

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

Но большинство моих разработчиков работают над уже развитой частью проекта. Там любую задачу я могу четко формализовать. К тому же, любая правка там должна быть под чутким контролем. Поэтому основная часть работы ведется именно так, как описано в статье — отдельный бранч на каждую, пусть даже мелкую, задачу.
Да, Redmine очень удобен. Я даже не работая в команде использую его как хранилище данных о проекте и сам себе задачи назначаю =). Плюс очень удобная вещь там — учет времени на задачу.
Раньше тоже использовал Trac.
а вебморды для gitosis не знаете? Чтобы пользователей и тд, добавлять через браузер
Нет, не возникало такой задачи. Но там же очень простой конфиг, так что я не заморачиваюсь, руками правлю.
UFO landed and left these words here
Эээ… Вы, простите, ерунду сказали. Файлы, которые должны быть изменены для работы на конкретной машине, вообще не должны быть под контролем git'а.

Скажем, логов в репозитории вообще не должно быть, а на конкретных машинах они должны быть проигнорированы путем создания файлов .gitignore. А конфиги должны быть внесены в репозиторий в виде файлов .orig и на конкретных машинах должны копироваться в новые файлы, опять же, игнорируемые через .gitignore.
UFO landed and left these words here
Вот именно про файлы типа конфигов Вы и говорили. А я сказал, как нужно делать, чтобы эти файлы и в репозитории трекались, и локально правились, и куда не надо не коммитились.

Настройте все правильно и юзайте -am, вместо ручного перечисления полусотни измененных файлов.
откуда полсотни то возьмется? непонятно зачем писать так код, чтобы в коммит попадало так много изменений за раз, на мой взгляд это плохая практика.
Ну как откуда? Это если задача «переименовать кнопку Сохранить в кнопку Записать», тогда конечно, в коммите будет одно изменение. А если задача «исправить функцию расчета Итого в финансовых отчетах», то изменений будет ого-го.
Я обычно перед тем, как делать коммит делаю git status и вижу, что пойдет в коммит. Поэтому -am можно небояться.
А все конфиги должны быть в .gitignore. А их default версии в файликах .default.
От чего-ж ерунду, а мой взгляд -a совсем не лучший вариант, я тоже всегда перечисляю весь список файлов для коммита, на мой взгляд так гораздо проще не запихать ерунды в коммит.
Т.е. Вы предлагаете иметь ерунду в файлах, и постоянно волноваться, чтобы эту ерунду не отправить в репозиторий? Нет уж, спасибо, я лучше вообще ну буду иметь ерунды.
Ерундой может оказаться случайно измененный файл (ненужный пробел, перевод строки, ...), вывод отладочной информации (к примеру излишне подробный логгинг) и тому подобные изменения.
Лучше всё-таки просматривать код до коммита (git add -p, git gui). В крайнем случае — git status + git diff + git commit -a.
чтобы в git commit не перечислять файлы, можно и нужно пользовать команду git add <маска_поиска_файлов>

После того как пометите все файлы которые идут в коммит (проверяете c помощью git status) использовать git commit -m «какой то коммит»
Я вот вообще hunk-ами стараюсь коммититься.

$ git add -p

рулит :-)

Коммитов больше, зато и контроля больше. Чётко видно, что, где и почему поменялось.
Во-первых, спасибо за статью!

Еще было бы интересно узнать, используется ли в Вашей разработке какой-то Ваш движок, CMS, или фреймфорк и как происходит его параллельная разработка вместе с работой над конкретным проектом (внешним).

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

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

Очень много искал на эту тему но пока ничего дельного не придумалось.
У меня нет отдельно CMS и отдельно проекта/проектов на ней. Разрабатывается проект, и все функции, которые проекту требуются, сразу в него и встраиваются. Проект узкоспецифический, коробочная версия не предполагается.
Я предпочитаю разделять такие вещи по разным проектам и работа с ними независимо. Управлять слиянием конфигурации и движка надо извне (например, системой управления зависимостями платформы).

А так для меня есть 2 подхода для решения описанной вами задачи средствами только git: git submodule и git subtree. Первый плох тем, что недостаточно объединяет подмодуль и его контейнер: имея репозиторий с контейнером можно не иметь понятия о том, где брать подмодуль и наоборот. Второй плох тем, что недостаточно устоялся и тем, что для выгрузки изменений из контейнера в репозиторий модуля надо делать промежуточное действие: выгрузку изменений подкаталога внутри репозитория контейнера.
Небоьшую путаницу вносит то, что вы употребляете слова «ветка» и «бренч» в одном предложении в разных значениях. Мозг автоматически вопринимает эти слова как синонимы :)

А по сути — спасибо большое. Действительно, подобных статей я не встречал, разобрано именно то, что вегда упускается.
Ммм… Я на самом деле использую эти слова как синонимы. Если где-то получилось предложение, в котором эти слова означают разное — скажите, я постараюсь переформулировать.
В тестовой ветке проверяемый бранч лежит и есть не просит. Когда заказчик доберется до него и утвердит, тогда я снова вытяну этот бранч из рабочего репозитория и солью с актуальной веткой."
Мда. Тут вместо слова «бранч» следовало бы употребить слово «коммит». Но тогда во всех остальных местах получается запутка… Я постараюсь переформулировать, спасибо за толковое замечание.
Но в одном репозитории нельзя разделить доступ к отдельным бранчам, т.е. нельзя разрешить писать в репозиторий новые бранчи и при этом запретить изменять актуальную ветку.

можно. используя pre-receive хук:

#!/bin/sh
while read a; do 
  branch=`echo $a | cut -d" " -f3`
  if [ $branch == "refs/heads/master" -o $branch == "refs/heads/stage" ];  then
    username=`whoami`
    if [ $username != 'superuser1' -a $username != 'superuser2' ];  then
      echo "* You not authorized to commit to $branch branch!!!        *" 1>&2
      exit 1
    fi
  fi
done


Также можно отослать себе email — с нотификацией, что кто-то хотел залиться в мастер.
Да, можно решить хуками. Но я тут рассуждаю так:

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

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

Поэтому я сразу разделяю главный репозиторий и репозитории отдельных разработчиков. Правда, я все-таки делаю упрощение и репозитории отдельных разработчиков объединяю в один.
Согласен, я лишь хотел заметить, что запретить коммитить в отдельно взятый бранч в одном репозитории возможно.
А в ядре, насколько я знаю, в основном пулят, а не пушат изменения.
В принципе если работа происходит в офисе и у суперразработчика есть доступ на все машины по ssh — то можно пулить в свой репозиторий прямо с персональных репозиториев;)
Но если в комманде есть редиска, который ходит на работу с ноутбуком — то всё становится тяжелее;)
Спасибо, статья вразумительная, однако с git не знаком совершенно. Возник такой, скорее всего, глупый вопрос: где девелоперы пишут код? :-)
Девелоперы вытягивают копию главного репозитория к себе. В свой домашний каталог, или вообще на свой собственный комп. Куда угодно, где им удобно работать. Там и пишут код. А потом отправляют то, что написали, в рабочий репозиторий.
Хочу дополнить ivanych`а, что для разработки web-приложений очень помогают отдельные виртуальные машины с Linux: если что, то можно быстро дать уже готовую и настроенную среду новому разработчику.
спасибо за статью, через недельку расскажу как происходит командная разработка с использованием git в проекте Midnight Commander…
Тоесть вы сами проверяете все изменения разработчиков? У вас нет отдела тестирования и continious integration? Я вот все думаю как заставить Hudson дружить с такой кучей веток.
Вот интересно как автор решает проблемы с бинарными файлами в репозитории (если они возникают конечно).
Поясню, что имею ввиду: хранить бинарники в vcs не очень хорошая идея, но иногда нет выхода. К примеру это может быть файл с ресурсами для флешки, картинки или схожие ресурсы у которых нету текстовых исходников.
Так вот, если разработка svn-like — то проблемы особо нет — ктото предупреждает остальных, что файл будет им изменен, меняет, заливает и освобождает этот ресурс. Но вот в случае если в мастер принимаются патчи и мёржатся одним человеком — пока он не смержит изменения — никто не может менять файл.
Я вижу пока только 2 варианта — не хранить файлы в vcs, но тогда дополнительно надо иметь доступ к хранилищу этих файлов (samba, NFS), а также у них не будет исптории. Или хранить в отдельном репозитории с svn-like подходом.
Товарищ описывает ситуацию следующего характера:

1. Разработчик (дизайнер) A пуллит бинарный файл F1 (например, картинку)
2. Разработчик (дизайнер) B пуллит бинарный файл F1
3. Разработчик А коммитит измененный файл F1/A в ветку B1
4. Разработчик B коммитит измененный файл F1/B в ветку B2
5. Вам нужны оба изменения на продакшне.

Ваши действия?
Понял.

Не знаю, как тут быть. У меня как-то не возникает таких ситуаций, поэтому четкой позиции у меня по этому поводу нет. Как столкнусь — напишу другую статью:)
Честно говоря, не понял сути описанной Вами проблемы.

У меня есть бинарные файлы. Вообще проект имеет, в основном, веб-интерфейс, но некоторая часть интерфейса, требовательная к графическим возможностям, реализована в виде исполняемого windows-приложения. Исходные коды приложения хранятся в репозитории, это понятно. Где хранить готовый дистрибутив — я тоже долго думал и решил хранить там же, в репозитории. Смысл в том, что в этом случае pull на продакшне автоматически деплоит дистрибутив на сервер, с которого дистрибутив уже могут скачать все пользователи.

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

Разница будет как минимум в том, что не девелоперы будут куда-то коммитить свой код, а вы будете pull-ить их код к себе в репозиторий.
Тут можно спорить, конечно. Во всяком случае большое спасибо за подробное описание того, как у вас происходит разработка. Таких статей действительно нехватает. Плюс в карму :-)
хорошая статья, но у меня есть пару замечаний:

* «git branch -D» исползуется толко в исключительных случаях т.к. он позволяет потерять данные. в 99% случаев лучше использовать «git branch -d» — ета команда вернёт ошибкы при попытке удаления бранча который не «замерджен» в текущий.
* также из моего опыта если в команде работают толковые люди то настолько тотальный контроль не обязателен. у нас любой может «мерджить» в master
* под gitosis обычно используют юзер git а не gituser :)
* также предложенный порядок ведения бранчей отличается от «канонического» с точностью до наоборот :)
по идее «master» (или trunk) это место куда сливают всё самое последнее (и куда все могут мерджить),
а как раз для стабилизации используют staging и production бранчи.
* Нет, "-D" я указал осознанно. Именно с той целью, чтобы не отвлекаться на чтение уведомлений о «неродственности» текущего и удаляемого бранчей. Разработчики никогда не сливают свои бранчи с актуальным, им расхождение удаляемого бранча с актуальным роли не играет. А я всегда в итоге удаляю присланный бранч, не зависимо от того, слил я его с актуальной веткой, или нет, поэтому мне сообщения от флага "-d" тоже не интересны.

* Я и говорю — тотал контроль не главное, главное — возможность отправлять правки в продакшн по одной, не дожидаясь одобрения заказчиком всего пакета правок, попавшего в master.

* это я для того, чтобы понятно назвать githost. Согласитесь, название хоста host — не очень говорящее:)

* это Вы про другую схему рассказываете. Я именно отказался от такой схемы, когда все валят все в master. Моя схема более универсальна и позволяет, если хочется, все-таки валить все в master на рабочем репозитории.
Ну вот, наконец-то внятная грамотная статья от поклонника git, где описан правильный процесс контроля версий в рамках командной разработки. А то как ни статья — так одни восторги, эпитеты и простое перечисление команд из мануала. Здесь же показан пример грамотной СМ-политики для команды. Причем, именно политики, а не разрозненых сведений.

Одним словом, респект.

В моей SCM-копилке есть несколько ссылок на политики ведения групповой разработки — как с использованием классических подходов, так и agile-методик (без привязки к инструментам). Теперь вот есть куда отдельно указать любителям DVCS.

Хоть статья уже и старая, но всё же рискну поднять вопрос.
В данный момент мы у себя в проекте используем очень похожую схему разработки. Но проблема в том, что у нас очень много программистов и процесс проведения веток на актуальную версию (продакшн) занимает очень много времени.
Может быть есть какие-то системы автоматизации мержа многих веток на мастер, пуш в мастер, а потом пулл на мастере и пр?
Средств подобной автоматизации не знаю, как-то не возникало такой необходимости. Но так вот сходу я бы сказал, что это задача не техническая, а организационная. Я бы выделил несколько ответственных программистов, которым поручил бы сборку крупных частей проекта из мелких веток. А потом уж эти крупные ветки сливал бы в мастер.
Та вот как раз и проблема в том, что в этом случае люди будут заниматься рутинной и «хомячковой» работой по сливанию веток в мастер. Это занимает много времени, которые можно было бы потратить на реализацию программистских задач.
Но Вы не можете поступить иначе. Какая бы ни была автоматизация, но кто-то должен принять ответственность за принятие кода в продакшен. Это не «хомячковая» работа, наоборот, это едва ли не более важная работа, чем собственно написание кода.

Если ответственному человеку приходится выполнять много однотипных действий, то их, конечно, следует автоматизировать. Но принимать решения все-равно кто-то должен.
Да-да, я понимаю. Речь идёт о моменте, когда задача оттестирована и уже на 100% готова в продакшн. И нужно её довести как можно меньшими человекозатратами. Приходится, к примеру, 2 раза в день выводить по по 15-20 веток в продакшн. И вот проводящему это совсем не в кайф, тратить столько времени.
Каждая задача на 100% оттестирована? И возможность взаимных конфликтов всех 15-20 веток протестирована?

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

Если же тестированием у вас занимается автоматизированная система, то на выходе у нее уже должна быть готовая ветка для продакшена, со всеми протестированными и слитыми ветками.
Пост порядком запылился ) Но все же мне интересно. Вы пишете, что нужно 2 репо. Я сейчас работаю с проектом на bitbucket, и там можно настроить ограничение на коммиты в конкретную ветку. Например, сделать так, чтобы в эту ветку могли отправлять коммиты (и удалять ее тоже) только отдельные пользователи. Я не знаю, это допилили сами разработчики bitbucket или такой функционал уже встроен в гит, но в этом случае держать 2 репо бесмысленно. Работа ведется с ветками так же, как у Вас с 2 репо.
Хотя, конечно, могу предположить, что это фича именно bitbucket, иначе бы вы не писали про 2 репо)
Пост был написан, когда Гитхаб еще только-только появился, а Гитлаб ещё вообще не появился. В тех условиях работать более чем с одним репозиторием было весьма заморочно, а настраивать один репозиторий для доступа было невозможно или тоже сложно. Поэтому работа с двумя репозиториями была неким компромиссом.

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

Так что, да, пост порядком запылился:) Но спасибо, вы навели меня на мысль написать новую версию статьи, с учетом текущих реалий.
Не совсем понимаю, чем работа с отдельными репозиториями отличается от работы с отдельными ветками в одном репозитории, объясните пожалуйста разницу. Единственный плюс (а в некоторых случаях скорее минус), который я вижу — изолирование разрабов друг от друга.
> изолирование разрабов друг от друга.

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

Есть и дополнительные плюшки — например, свой репозиторий можно утащить с собой в лес и там разрабатывать в тишине и медитации.
А как таким образом решается вопрос с код ревью или, например, совместной работой над каким-то кодом? Простой пример. Есть некая фича, достаточно массивная. Делим на отдельные части, даем каждому разрабу отдельную часть. Когда части закончены, нужно выполнить их подключение друг к другу. Как показывает опыт, очень часто бывает, что нужно допиливать напильником уже вместе, а не по отдельности. И вот тут может очень пригодиться код другого разработчика. Если репо один, таких проблем не возникает. А как быть в этом случае, если у каждого разраба свой репо?
Происходит обмен кодом с другими репозиториями. В том и суть распределенной системы — не огородить всех неприступной стеной, а сделать сеть, с удобным доступом друг к другу.

Простите, я не готов в рамках комментария это описывать, это Вам лучше почитать в целом о Гите и пулл-реквестах.
Про пулл-реквесты я в курсе, только не знал, что их можно выполнять в другие репо. В целом, я понял, в чем профит от такого подхода, спасибо.
Касательно веток — у каждого разраба в своем репозитории могут быть ветки с каким угодно названием. Если все разрабы будут работать в одном репозитории, неминуемо будет конфликт имен — Вася назвал ветку «check» и Петя тоже так назвал — и привет, иди ругайся, кто тут главный.

Разнесение по разным репозиториям — это, в частности, разнесение по разным пространствам имен.
У нас такая проблема решается просто дописыванием в начале имени и фамилии разраба, например, вот так i_ivanov_название_ветки. Пока проблем нет. Хотя проект небольшой, возможно поэтому особых проблем пока не испытываем.
Это костыль, добавление префикса какбэ и намекает Вам, что нужны разные пространства имен:)
Для этого как раз удобен подход, продвигаемый гитлабом, где ветка начинается с номера задачи — это и решает вопрос уникальности имён (хотя в случае ветки на задачу каждая ветка и так будет называться по-разному), и добавляет простоту переключения на ветку вводом одного только номера задачи и автодополнением по табу.
Only those users with full accounts are able to leave comments. Log in, please.