Git, шпаргалка

Общие сведения по GIT

Структура репозитория

Итак, в типовом сценарии у нас есть:

  • расшаренный для доступа по сети центральный репозиторий;
  • репозиторий на каждом из серверов (продакшн и тестовые), обновляются pull’ом из центрального, не расшарены, наружу не торчат;
  • репозиторий у каждого из разработчиков (или несколько, как удобно), обновляются pull’ом из центрального, push’атся в центральный.

Соответственно основной реп — центральный. В достаточно большом/сложном проекте (а иначе нет смысла и говорить) структура веток у него следующая:

  • master — основная ветка разработки, пред-продакшн. Запрещено сознательно оставлять ошибки и недоработки в этой ветке, т.к. ветвь будет мержиться в production в произвольные моменты времени;
  • production-xxx — ветки продакшна. Одна или несколько. На обновление с них настроен продакшн сервер, коммитить туда напрямую строго запрещено, в общем случае могут находиться в ином репозитории, чем master, и доступ на запись к этим репозиториям есть только у отдельных разработчиков;
  • test-xxx — ветки для тестирования, с них обновляются тест-сервера (каждый со своей). В них можно творить что угодно. Если что — ветка убивается, и создается заново как клон master. В эти ветки можно мержить, коммитить, в общем что угодно. НО! Следует учитывать эфемерность этих ветвей. Вести разработку в них запрещено, т.к. ваши изменения будут утеряны при очистке ветви. Из этих ветвей мержи не делаются никуда и никогда, это тупиковые ветки. Их содержимое не предопределено, может содержать ошибки или просто отсутствовать;
  • stage — ветка будет создана при разработке очередного большого обновления. Аналог master, но для разработки, допускаются ошибки;
  • feature-nnn, hotfix-nnn — о них ниже.

Основные моменты, некоторые тонкости и пояснения

Как обычно — файлы в кодировке UTF-8, перенос строк UNIX. Пробелы в концах строк не допускаются, желательно включить автоматическую их очистку в вашем редакторе.

Операции rebase допускаются только для тех ревизий, которые не были опубликованы через push.

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

Еще мануалы:

Момент, который часто вызывает затруднения, особенно при переходе с других систем контроля версий — у GIT есть следующие места для хранения файлов:

  • собственно репозиторий: файлы внутри каталога .git, аналог репозитория SVN. Голыми руками от туда ничего не получить, формат хранения типа базы данных, да туда и не надо лезть;
  • рабочая копия: обычные файлы проекта. С ними и будет происходить работа;
  • индекс: промежуточная область (физически тоже живет внутри .git), в которой формируется будущий коммит. Операция коммита переносит индекс в репозиторий. Выделение индекса в отдельную сущность позволяет коммитить изменения в рабочей копии по частям. Следующие команды полезны:
    • git reset — очищает индекс;
    • git add файл — добавляет новый файл (или все произведенные в нем изменения, если файл уже есть в репозитории) в индекс;
    • git commit -a — добавляет все изменения файлов, включая удаление, но не новые файлы, в индекс и сразу же коммитит в репозиторий.
  • «заначка» (stash) — тоже физичесеи живет в .git, предназначена для временного «ныкания» изменений, когда необходимо переключиться на другую задачу, а текущая еще не готова. Команды:
    • git stash — скинуть в заначку все изменения рабочей копии и индекса, и соответственно убрать эти изменения. Состояние рабочей копии возвращается к такому, как будто вы никаких изменений не вносили;
    • git stash pop — достать заначку и применить ее к текущей рабочей копии. При этом сама заначка удаляется.

Также есть такая возможность, чтобы GIT не ругался на измененные файлы (и не пытался их коммитить по git commit -a):

  • git update-index --assume-unchanged файл скажет git’у чтобы он игнорировал изменения в соответствующем файле;
  • git update-index --no-assume-unchanged файл вернет обратно мониторинг этого файла.

Сие полезно для таких файлов как .htaccess.

Порядок работы

Начало

Перед началом работы необходимо:

  • установить git. В линухах git есть в дистрибутивах, для винды ссылка выше, ссылка для маков — http://code.google.com/p/git-osx-installer/
    • с некоторых пор инсталлятор git под windows стал предлагать выбор ssh бекенда между putty и openssh. Работают они оба, но эта шпаргалке описывает работу с openssh бекендом, т.к. он везде ведет себя и настраивается одинаково, и в винде и в линухе и на маках;
  • в git настроить ваше имя и e-mail. E-mail должен соответствовать e-mail’у в трекере;
  • коррекция переноса строк должна быть отключена! Не дело системы контроля версий этим заниматься, как в реп залито так и должно быть.

Т.е. конфигурация должна быть такой (само собой имя и почту следует указывать свои):

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
$ git config --global core.autocrlf false

Для начала работы необходимо склонировать центральный репозиторий: git clone центральный_реп:проект

Для пользователей windows — следует убрать контроль прав доступа на файлы. Делается в каждом репозитории (находясь в каталоге с репозиторием):

$ git config core.filemode false

В GIT обычно авторизация производится по ssh ключу. Соответственно для получения доступа к репозиторию вам необходимо предоставить менеджеру проекта ваш публичный ssh ключ. Если его нет — его следует сгенерировать. В винде это делается следующим образом: в «Git Bash» набираете ssh-keygen, нажимаете ентер на все вопросы, и в результате ключ должен сгенерироваться в файле «documents and settings\user\.ssh\id_rsa.pub». Ключ текстовый, его можно открыть блокнотом и скопипастить, а можно выслать в письме как есть. Имя файла ключа важно, если вы сохраните его под другим именем, то git файл не найдет и авторизация работать не будет.

В винде доступ к консольным командам git осуществляется через «Git Bash». С графическим интерфейсом рекомендую проявлять осторожность. Не забыть указать кодировку UTF-8!

Перед первым запуском Git GUI необходимо выполнить указанные выше команды для конфигурирования GIT, а также для генерации ключа. И предоставить менеджеру проекта публичный ключ для включения доступа!

Общий порядок работы

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

Базовые правила:

  1. в production напрямую не коммитить, только мержем из master;
  2. в master не пушить откровенной лажи и недопилов (для недопилов используйте отдельные ветки, случайно попавшую в master лажу фиксить максимально оперативно хотя-бы до состояния «не падает», а лучше заранее тестить и не пихать в мастер хуиты);
  3. если что-то запушили, то нельзя делать операции rebase над этими коммитами;
  4. если правка больше чем на 10 минут работы и/или предположительно она потребует проверки на тестовом — заводите под нее специальный бранч (feature-nnn, hotfix-nnn);
  5. если этой правкой хочется поделиться с остальными до состояния ее готовности — пушите ее бранч в центральный реп (в отдельную ветку само собой);
  6. если хочется что-то протестировать — мержите свои изменения в ветку test-xxx (см. п. 4);

Далее как обеспечить порядок работы таким образом чтобы вышеприведенное можно было выполнять без особого гемора:

  1. обновляем локальный репозиторий: git pull
  2. создаем ветку для работы на основе master: git checkout -b feature-nnn master
  3. вносим изменения
  4. при желании протестировать изменения:
    1. переключаемся в нужную ветку тестирования git checkout test-xxx
    2. мержим рабочую ветку в тестируемую: git merge feature-nnn
    3. пушим наши изменения на сервер: git push
    4. обновляем ветку на сервере тестирования: ssh server; cd path; git pull;
    5. просим тестеров тестировать или тестируем самостоятельно
    6. если какие либо проблемы — не забываем переключаться обратно на ветку git checkout feature-nnn повторяем с п. 3
  5. когда фича/багфикс готовы мержим их в мастер и пихаем на сервер:
    1. git checkout master
    2. git merge feature-nnn
    3. git push
  6. Когда все что надо сделано, и мастер явно рабочий, мержим мастер с продакшном
    1. git checkout production
    2. git merge master
    3. git push
    4. Обновляем продакшн: ssh production; cd path; git pull

Если изменение тривиально (один коммит, явно простой), то п.п. 2-4 можно опустить (разместить этот коммит напрямую в master). Внимание! Такое действие следует производить крайне осторожно!

Сокращенный порядок работы (при условии наличия собственного окружения для тестирования):

  1. работаем в master;
  2. вносим багфикс как обычно, проверяем до состояния работоспособности;
  3. когда фикс готов — пушим в master центрального репа;
  4. мержим master в production.

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

Именование и работа с ветками hotfix и feature

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

Если ваше изменение заключается в исправлении ошибки, то ветвь следует называть hotfix-. Если это новый функционал, то feature-. После «-» следует указать номер тикета в трекинге (если таковой есть, в противном случае для hotfix ОБЯЗАТЕЛЬНО необходимо создать тикет, для feature — крайне желательно). Если для feature нет тикета и по каким-либо причинам создавать его нет возможности — следует заменить номер одним-двумя словами характеризующими фичу. Также такую пару слов можно добавить к номеру тикета если фича достаточно объемна. В принципе если вы абсолютно точно уверены, что не будете размещать эту ветку в центальном репозитории и не запутаетесь в ветках, то можно называть ветви иначе. Но крайне рекомендуется придерживаться этой схемы, т.к. заранее можно не угадать.

Если багфикс залит в master, протестирован и готов, то локальную ветку можно удалить: git branch -d hotfix-nnn

Если для бранча требуется совместная работа нескольких разработчиков, то допускается размещение его в центральном репозитории: git push origin feature-nnn:feature-nnn, соответственно при работе с таким бранчем следует не забывать делать git pull/git push, также в такой фича-бранч допускается мерж master бранча (если фича действительно большая и довольно долго реализуется).

Решение проблем

  1. На венде Git не любит русские буквы в путях, особенно в путях к домашнему каталогу (т.е. в именах учетных записей);
  2. Если Git GUI на винде не запускается с дикой ошибкой (такое бывает если при первом запуске склонировать репозиторий не удалось), то следует удалить файл «documents and settings\user\.gitconfig» (не забыть после этого заново прописать заново настройки, имя и e-mail).
  3. Если по п. 4.6 порядка работы забыли переключиться в рабочий бранч и скоммитили напрямую в тестируемый, то есть следующие варианты:
    1. Если не успели запушить изменения, то можно удалить последний коммит из истории через git reset --soft HEAD^, переключить бранч и скоммитить по новой;
    2. Если уже успели: переключаемся в рабочий бранч, и применяем сделанный ранее коммит: git cherry-pick nnnnnnnnn (id коммита можно узнать по git log);
    3. Другой вариант, если изменения еще не запушены: аналогично предыдущему пункту через cherry-pick применяете коммит к рабочему бранчу, переключаетесь в тестовый, и через git rebase -i HEAD^^ удаляете коммит. Потом можно смержить рабочий бранч в тестовый, и коммит таким образом вернется. Зачем такие сложности? Затем что cherry-pick создает НОВЫЙ коммит, а мерж не создает и применяет существующий. Соответственно если коммит не удалить, то в трекере/истории и т.п. он будет виден два раза, но не будет видно что это одно и то же, и связи между ними не будет.

Автоматизация

Простой скрипт для мержа мастера в продакшн (одновременно обновит рабочую копию и запушит мерж):

#!/bin/sh

git checkout master && git pull && git checkout production && git pull origin production && git merge master && git push 
git checkout master && git push