15 июл. 2013 г.

Git: командная работа

Git: командная работа

Все приличные команды разработки работают с таск-трекерами, сейчас как мне кажется стандартом стал Jira (ну или другой трекер, суть та же для примера). Поэтому здесь для примера буду писать "таск" или "тикет" подразумевая задачу в Jira. Хорошим тоном сейчас считается указание идентификатора таска в каждом коммите который для решения этого таска делается. Не претендую на истину в последней инстанции, но как один из возможных вариантов опишу здесь свой опыт. Могу дополнить только что для SVN пользовался практически той же схемой, за исключением того, что ветвление на каждую задачу значительно безопаснее как мне кажется, но об этом ниже.

Итого:
  1. В команде есть NN разработчиков
  2. Все разработчики используют единый репозиторий git
  3. В репозитории существуют две (может быть для каких-то целей и больше) основные ветки master и dev
  4. Ветка master существует исключительно для стабильных версий продукта, работающих только в боевой (продакшн) зоне. То есть эта ветка считается последней стабильной версией ПО с которой работают конечные пользователи. Перед каждым релизом на эту ветку ставится тег, с которого собственно и выкатывается стабильная версия. В случае каких-то проблем на боевой откатывается на предыдущий стабильный тег этой ветки (если такой откат возможен конечно после внесенных изменений в БД или какие-то другие жизненно важные части по).
  5. Ветка dev (development) служит для аккумулирования изменений всех изменений разработчиков и собственно обмена последними стабильными изменениями между разработчиками.
  6. Для каждой новой задачи разработчик создает новую ветку от текущей dev и работает в ней, с нее же получая для своей задачи обновления по необходимости
  7. При передаче в тест разработчик синхронизирует свою ветку с текущей dev и отдает на тестирование свою задачу именно на ветке этой задачи
  8. После тестирования разработчик мерджит свою ветку в dev и либо сам проверяет что ничего не сломалось уже на dev либо это опять проверяют тестеры
  9. Перед релизом dev ветка мерджится на master, после чего на мастере ставится тег с которого производится деплой свежего релиза
Вот таким вот нехитрым способом все происходит. Схема вполне рабочая, но возможно можно что-то улучшить, сейчас - как есть.
Что касается git, то описанный процесс происходит примерно так:
  1. Клонируем репозиторий в папку (если необходимо)
    cd /my/project/folder
    git clone ssh://luke@tatuin.com/git/project-repo .
    
  2. Переключаемся на dev ветку и обновляем ее
    git checkout dev
    git pull origin dev
    
  3. Ветвимся от dev в ветку под конкретную задачу (для примера имя ветки здесь это ключ от таска в Jira)
    git checkout -b task-123
    git status
    
    Статус должен показать что вы теперь на ветке task-123
  4. Теперь спокойно работаем на этой ветке и все коммиты по задаче идут на неё
    git commit -am 'task-123 my task commit'
    
  5. Если задача затянулась, то можно подтянуть на ветку обновления от других разработчиков
    git pull origin dev
    
    Для того чтобы сделать pull в этой ситуации, нужно либо все свои изменения закомитить на ветку, либо воспользоваться git stash чтобы спрятать свои изменения, а потом git stash apply чтобы достать свои изменения назад. При каждом коммите нужно тщательно смотреть diff.
  6. Когда задача закончена, и все коммиты по ней отправлены на соответствующую ветку отправляем свою ветку в общий репозиторий
    git push origin test-123
    
    Таким образом ветка станет доступна другим разработчикам и тестерам. Все, в этот момент останавливаем прогресс в таск-трекере и передаем задачу в тестирование.
  7. Посмотреть все лоакльные ветки можно вот так
    git branch
    
    Посмотреть все ветки в удаленном репозитории можно вот так
    git branch --remote
    
  8. Теперь задачу нам вернули из теста, с ней все хорошо, нужно вмерджить свои изменения в dev ветку
    git checkout dev
    git pull origin dev
    git merge test-123
    
    Тут мы переключаемся на dev ветку, обновляем её содержимое из удаленного репозитория и собственно мерджим в ветку dev свою ветку test-123. При необходимости все конфликты разрешаем ручками и коммитим, но уже на dev. Теперь осталось только отправить наши изменения на dev-e в удаленный репозиторий
    git push origin dev
    
  9. Теперь желательно прибрать за собой, то есть убрать больше не нужные ветки. Сначала удалим ветку из удаленного репозитория
    git push origin :test-123
    
    А теперь ветку в локальном репозитории
    git branch -d test-123
    
На этом собственно и все. В начале работы по такой схеме часто возникают типовые ошибки:
  • Работа на другой ветке (забыл переключиться в спешке), тут может выручить stash. С его помощью можно спрятать изменения, а потом выложить их на другой ветке после переключения на неё, важно внимательно смотреть в diff при коммитах чтобы не потереть чужое.
  • Пуш в другую ветку, тут нужно просто быть внимательным при каждом push-e.
  • Ошибки связанные с мерджем, тут тоже нужно помнить что нужно сначала перейти в ветку в которую будем мерджить свои изменения, а уже потом мерджить в неё свою ветку. Нужно просто быть внимательным.
При внешней сложности через пару недель все это прочно оседает в голове и делается почти автоматически. Важно просто быть внимательным в начале работы по этой схеме чтобы не наломать дров в общем репозитории. Особо внимательно стоит смотреть на диффы и во время пушей, что, откуда и куда пушим. Если не сильно торопиться то проблем не будет.